<commit_before>/* jshint ignore:start */
// Shims, polyfills, etc.

require('intl/Intl.min');

// dataset
Function.prototype.bind||(Function.prototype.bind=function(e){"use strict";if(typeof this!="function")throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var t=Array.prototype.slice.call(arguments,1),n=this,r=function(){},i=function(){return n.apply(this instanceof r&&e?this:e,t.concat(Array.prototype.slice.call(arguments)))};return r.prototype=this.prototype,i.prototype=new r,i}),function(){"use strict";var e=Object.prototype,t=e.__defineGetter__,n=e.__defineSetter__,r=e.__lookupGetter__,i=e.__lookupSetter__,s=e.hasOwnProperty;t&&n&&r&&i&&(Object.defineProperty||(Object.defineProperty=function(e,o,u){if(arguments.length<3)throw new TypeError("Arguments not optional");o+="";if(s.call(u,"value")){!r.call(e,o)&&!i.call(e,o)&&(e[o]=u.value);if(s.call(u,"get")||s.call(u,"set"))throw new TypeError("Cannot specify an accessor and a value")}if(!(u.writable&&u.enumerable&&u.configurable))throw new TypeError("This implementation of Object.defineProperty does not support false for configurable, enumerable, or writable.");return u.get&&t.call(e,o,u.get),u.set&&n.call(e,o,u.set),e}),Object.getOwnPropertyDescriptor||(Object.getOwnPropertyDescriptor=function(e,t){if(arguments.length<2)throw new TypeError("Arguments not optional.");t+="";var n={configurable:!0,enumerable:!0,writable:!0},o=r.call(e,t),u=i.call(e,t);return s.call(e,t)?!o&&!u?(n.value=e[t],n):(delete n.writable,n.get=n.set=undefined,o&&(n.get=o),u&&(n.set=u),n):n}),Object.defineProperties||(Object.defineProperties=function(e,t){var n;for(n in t)s.call(t,n)&&Object.defineProperty(e,n,t[n])}))}();if(!document.documentElement.dataset&&(!Object.getOwnPropertyDescriptor(Element.prototype,"dataset")||!Object.getOwnPropertyDescriptor(Element.prototype,"dataset").get)){var propDescriptor={enumerable:!0,get:function(){"use strict";var e,t=this,n,r,i,s,o,u=this.attributes,a=u.length,f=function(e){return e.charAt(1).toUpperCase()},l=function(){return this},c=function(e,t){return typeof t!="undefined"?this.setAttribute(e,t):this.removeAttribute(e)};try{(({})).__defineGetter__("test",function(){}),n={}}catch(h){n=document.createElement("div")}for(e=0;e<a;e++){o=u[e];if(o&&o.name&&/^data-\w[\w\-]*$/.test(o.name)){r=o.value,i=o.name,s=i.substr(5).replace(/-./g,f);try{Object.defineProperty(n,s,{enumerable:this.enumerable,get:l.bind(r||""),set:c.bind(t,i)})}catch(p){n[s]=r}}}return n}};try{Object.defineProperty(Element.prototype,"dataset",propDescriptor)}catch(e){propDescriptor.enumerable=!1,Object.defineProperty(Element.prototype,"dataset",propDescriptor)}};

// Array.prototype.some
Array.prototype.some||(Array.prototype.some=function(a){"use strict";if(null==this)throw new TypeError("Array.prototype.some called on null or undefined");if("function"!=typeof a)throw new TypeError;for(var b=Object(this),c=b.length>>>0,d=arguments.length>=2?arguments[1]:void 0,e=0;c>e;e++)if(e in b&&a.call(d,b[e],e,b))return!0;return!1});

// Array.from
Array.from||(Array.from=function(){var a=Object.prototype.toString,b=function(b){return"function"==typeof b||"[object Function]"===a.call(b)},c=function(a){var b=Number(a);return isNaN(b)?0:0!==b&&isFinite(b)?(b>0?1:-1)*Math.floor(Math.abs(b)):b},d=Math.pow(2,53)-1,e=function(a){var b=c(a);return Math.min(Math.max(b,0),d)};return function(a){var c=this,d=Object(a);if(null==a)throw new TypeError("Array.from requires an array-like object - not null or undefined");var g,f=arguments.length>1?arguments[1]:void 0;if("undefined"!=typeof f){if(!b(f))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(g=arguments[2])}for(var k,h=e(d.length),i=b(c)?Object(new c(h)):new Array(h),j=0;h>j;)k=d[j],f?i[j]="undefined"==typeof g?f(k,j):f.call(g,k,j):i[j]=k,j+=1;return i.length=h,i}}());

// Object.assign, useful for merging objects
if (!Object.assign) {
  Object.defineProperty(Object, "assign", {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target, firstSource) {
      "use strict";
      if (target === undefined || target === null)
        throw new TypeError("Cannot convert first argument to object");

      var to = Object(target);

      var hasPendingException = false;
      var pendingException;

      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource === undefined || nextSource === null)
          continue;

        var keysArray = Object.keys(Object(nextSource));
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
          var nextKey = keysArray[nextIndex];
          try {
            var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
            if (desc !== undefined && desc.enumerable)
              to[nextKey] = nextSource[nextKey];
          } catch (e) {
            if (!hasPendingException) {
              hasPendingException = true;
              pendingException = e;
            }
          }
        }

        if (hasPendingException)
          throw pendingException;
      }
      return to;
    }
  });
}

if (!Number.isInteger) {
  Object.defineProperty(Number, 'isInteger', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(n) {
      return n === +n && n === (n|0);
    }
  });
}
/* jshint ignore:end */

if (!Array.prototype.find) {
  Array.prototype.find = function(predicate) {
    if (this === null) {
      throw new TypeError('Array.prototype.find called on null or undefined');
    }
    if (typeof predicate !== 'function') {
      throw new TypeError('predicate must be a function');
    }
    var list = Object(this);
    var length = list.length >>> 0;
    var thisArg = arguments[1];
    var value;

    for (var i = 0; i < length; i++) {
      value = list[i];
      if (predicate.call(thisArg, value, i, list)) {
        return value;
      }
    }
    return undefined;
  };
}

// ReactDOM
window.ReactDOM = React;
<commit_msg>Use en locale data by default<commit_after>/* jshint ignore:start */
// Shims, polyfills, etc.

require('intl/Intl.min');
require('intl/locale-data/jsonp/en.js');

// dataset
Function.prototype.bind||(Function.prototype.bind=function(e){"use strict";if(typeof this!="function")throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var t=Array.prototype.slice.call(arguments,1),n=this,r=function(){},i=function(){return n.apply(this instanceof r&&e?this:e,t.concat(Array.prototype.slice.call(arguments)))};return r.prototype=this.prototype,i.prototype=new r,i}),function(){"use strict";var e=Object.prototype,t=e.__defineGetter__,n=e.__defineSetter__,r=e.__lookupGetter__,i=e.__lookupSetter__,s=e.hasOwnProperty;t&&n&&r&&i&&(Object.defineProperty||(Object.defineProperty=function(e,o,u){if(arguments.length<3)throw new TypeError("Arguments not optional");o+="";if(s.call(u,"value")){!r.call(e,o)&&!i.call(e,o)&&(e[o]=u.value);if(s.call(u,"get")||s.call(u,"set"))throw new TypeError("Cannot specify an accessor and a value")}if(!(u.writable&&u.enumerable&&u.configurable))throw new TypeError("This implementation of Object.defineProperty does not support false for configurable, enumerable, or writable.");return u.get&&t.call(e,o,u.get),u.set&&n.call(e,o,u.set),e}),Object.getOwnPropertyDescriptor||(Object.getOwnPropertyDescriptor=function(e,t){if(arguments.length<2)throw new TypeError("Arguments not optional.");t+="";var n={configurable:!0,enumerable:!0,writable:!0},o=r.call(e,t),u=i.call(e,t);return s.call(e,t)?!o&&!u?(n.value=e[t],n):(delete n.writable,n.get=n.set=undefined,o&&(n.get=o),u&&(n.set=u),n):n}),Object.defineProperties||(Object.defineProperties=function(e,t){var n;for(n in t)s.call(t,n)&&Object.defineProperty(e,n,t[n])}))}();if(!document.documentElement.dataset&&(!Object.getOwnPropertyDescriptor(Element.prototype,"dataset")||!Object.getOwnPropertyDescriptor(Element.prototype,"dataset").get)){var propDescriptor={enumerable:!0,get:function(){"use strict";var e,t=this,n,r,i,s,o,u=this.attributes,a=u.length,f=function(e){return e.charAt(1).toUpperCase()},l=function(){return this},c=function(e,t){return typeof t!="undefined"?this.setAttribute(e,t):this.removeAttribute(e)};try{(({})).__defineGetter__("test",function(){}),n={}}catch(h){n=document.createElement("div")}for(e=0;e<a;e++){o=u[e];if(o&&o.name&&/^data-\w[\w\-]*$/.test(o.name)){r=o.value,i=o.name,s=i.substr(5).replace(/-./g,f);try{Object.defineProperty(n,s,{enumerable:this.enumerable,get:l.bind(r||""),set:c.bind(t,i)})}catch(p){n[s]=r}}}return n}};try{Object.defineProperty(Element.prototype,"dataset",propDescriptor)}catch(e){propDescriptor.enumerable=!1,Object.defineProperty(Element.prototype,"dataset",propDescriptor)}};

// Array.prototype.some
Array.prototype.some||(Array.prototype.some=function(a){"use strict";if(null==this)throw new TypeError("Array.prototype.some called on null or undefined");if("function"!=typeof a)throw new TypeError;for(var b=Object(this),c=b.length>>>0,d=arguments.length>=2?arguments[1]:void 0,e=0;c>e;e++)if(e in b&&a.call(d,b[e],e,b))return!0;return!1});

// Array.from
Array.from||(Array.from=function(){var a=Object.prototype.toString,b=function(b){return"function"==typeof b||"[object Function]"===a.call(b)},c=function(a){var b=Number(a);return isNaN(b)?0:0!==b&&isFinite(b)?(b>0?1:-1)*Math.floor(Math.abs(b)):b},d=Math.pow(2,53)-1,e=function(a){var b=c(a);return Math.min(Math.max(b,0),d)};return function(a){var c=this,d=Object(a);if(null==a)throw new TypeError("Array.from requires an array-like object - not null or undefined");var g,f=arguments.length>1?arguments[1]:void 0;if("undefined"!=typeof f){if(!b(f))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(g=arguments[2])}for(var k,h=e(d.length),i=b(c)?Object(new c(h)):new Array(h),j=0;h>j;)k=d[j],f?i[j]="undefined"==typeof g?f(k,j):f.call(g,k,j):i[j]=k,j+=1;return i.length=h,i}}());

// Object.assign, useful for merging objects
if (!Object.assign) {
  Object.defineProperty(Object, "assign", {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target, firstSource) {
      "use strict";
      if (target === undefined || target === null)
        throw new TypeError("Cannot convert first argument to object");

      var to = Object(target);

      var hasPendingException = false;
      var pendingException;

      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource === undefined || nextSource === null)
          continue;

        var keysArray = Object.keys(Object(nextSource));
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
          var nextKey = keysArray[nextIndex];
          try {
            var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
            if (desc !== undefined && desc.enumerable)
              to[nextKey] = nextSource[nextKey];
          } catch (e) {
            if (!hasPendingException) {
              hasPendingException = true;
              pendingException = e;
            }
          }
        }

        if (hasPendingException)
          throw pendingException;
      }
      return to;
    }
  });
}

if (!Number.isInteger) {
  Object.defineProperty(Number, 'isInteger', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(n) {
      return n === +n && n === (n|0);
    }
  });
}
/* jshint ignore:end */

if (!Array.prototype.find) {
  Array.prototype.find = function(predicate) {
    if (this === null) {
      throw new TypeError('Array.prototype.find called on null or undefined');
    }
    if (typeof predicate !== 'function') {
      throw new TypeError('predicate must be a function');
    }
    var list = Object(this);
    var length = list.length >>> 0;
    var thisArg = arguments[1];
    var value;

    for (var i = 0; i < length; i++) {
      value = list[i];
      if (predicate.call(thisArg, value, i, list)) {
        return value;
      }
    }
    return undefined;
  };
}

// ReactDOM
window.ReactDOM = React;
<|endoftext|>


<commit_before>"use strict";
/*jshint eqnull:true */
/*jshint globalstrict:true */
/*jshint node:true */
/* global describe */
/* global it */

var expect = require('expect.js');
var sinon = require('sinon');
var Promises = require('best-promise');
var qacServices = require('../lib/qac-services.js');
var fs = require('fs-promise');
var helper=require('../test/test-helper.js');
var html = require('js-to-html').html;
var Path = require('path');
helper.setup(qacServices);

describe("qac-services overview",function(){
    it("get cucardasToHtmlList",function(){
        var obt=qacServices.cucardasToHtmlList(
            "[![npm-version](https://img.shields.io/npm/v/multilang.svg)](https://npmjs.org/package/multilang)  \n\r "+
            "[![downloads](https://img.shields.io/npm/dm/multilang.svg)](https://npmjs.org/package/multilangx) "+
            "![extending](https://img.shields.io/badge/stability-extending-orange.svg)"+
            "![stable](https://img.shields.io/badge/stability-stable-green.svg)"+
            "![otra](https://img.shields.io/badge/stability-otra-green.svg)"+
            "![otra-mas](https://img.shields.io/badge/stability-otra-mas-green.svg)"
        );
        //console.log("obt", obt);
        expect(obt).to.eql([
            html.td({class:'centrado'}, [
                html.img({src:"https://img.shields.io/badge/stability-extending-orange.svg", alt:"extending"}),
                html.img({src:"https://img.shields.io/badge/stability-stable-green.svg", alt:"stable"})
            ]),
            html.td({class:'centrado'}, [
                html.a(
                    {href:"https://npmjs.org/package/multilang"},
                    [ html.img({src:"https://img.shields.io/npm/v/multilang.svg", alt:"npm-version"}) ]
                ),
            ]),
            html.td({class:'centrado'}, [
                html.a(
                    {href:"https://npmjs.org/package/multilangx"},
                    [ html.img({src:"https://img.shields.io/npm/dm/multilang.svg", alt:"downloads"}) ]
                ),
            ]),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}, [
                html.img({src:"https://img.shields.io/badge/stability-otra-green.svg", alt:"otra"}),
                html.img({src:"https://img.shields.io/badge/stability-otra-mas-green.svg", alt:"otra-mas"})
            ])
        ]);
    });
    it("get projectNameToHtmlLink",function(){
        var oriUrl = qacServices.rootUrl;
        qacServices.rootUrl='/root/'
        var obt=qacServices.projectNameToHtmlLink('simple-org','proj-name');
        expect(obt).to.eql(
            html.a({href:"/root/simple-org/proj-name"}, "proj-name")
        );
        qacServices.rootUrl = oriUrl;
    });
    it("get projectActionButtons",function(){
        var oriUrl = qacServices.rootUrl;
        qacServices.rootUrl='/root/';
        qacServices.user='user-name';
        qacServices.production=false;
        var obt=qacServices.projectActionButtons('simple-org','proj-name');
        expect(obt).to.eql([
            html.td([
                html.a({
                    href: '/root/ask/delete/simple-org/proj-name',
                    'codenautas-confirm': 'row'
                },[html.img({src:'/delete.png', alg:'del', style:'height:18px'})])
            ]),
            html.td([
                html.a({
                    href:'/root/manual-push/simple-org/proj-name'
                }, [html.img({src:'/refresh.png', alt:'rfrsh', style:'height:18px'})])
            ])
        ]);
        qacServices.production=true;
        qacServices.user=false;
        qacServices.rootUrl = oriUrl;
    });
    describe('organization page',function() {
        function checkGetOrg(msg, result, userLogged) {
            it(msg, function(done) {
                sinon.stub(qacServices, "getInfo", function(organization, project){
                    if(!!project){
                        throw new Error("unexpected project name in getInfo");
                    }
                    if(organization!=='simple'){
                        throw new Error("wrong organization name in getInfo");
                    }
                    return Promises.resolve({
                        organization:{
                            projects:[{
                                projectName:'uno'
                            },{
                                projectName:'dos'
                            }],
                            path:'the-org-path',
                            name:organization
                        }
                    });
                });
                sinon.stub(fs, 'readFile', function(nameCucardas){
                    //console.log("nameCucardas", nameCucardas);
                    switch(nameCucardas){
                        case Path.normalize('the-org-path/projects/uno/result/cucardas.md'): return Promises.resolve('[qa-control][issues] cu-uno');
                        case Path.normalize('the-org-path/projects/dos/result/cucardas.md'): return Promises.resolve('[qa-control][issues] cu-dos');
                        default: throw new Error('unexpected params in readFile of cucardas');
                    }
                });
                sinon.stub(qacServices, "cucardasToHtmlList", function(x){
                    return [html.td("list: "+x)];
                });
                sinon.stub(qacServices, "projectActionButtons", function(orga, proj){
                    return [html.td("b:"+orga+':'+proj)];
                });
                sinon.stub(qacServices, "projectNameToHtmlLink", function(orga, proj){
                    return "link: "+orga+','+proj;
                });
                sinon.stub(qacServices, "sortProjects", function(proj1, proj2) {
                   if(proj1 < proj2) {
                       return -1;
                   } else if(proj1 > proj2) {
                       return 1;
                   }
                   return 0;
                });
                if(userLogged) {
                    qacServices.user = 'pepe';
                }
                qacServices.getOrganizationPage('simple').then(function(oHtml){
                    //console.log(oHtml.toHtmlText({pretty:true}));
                    expect(oHtml).to.eql(result);
                }).then(function(){
                    qacServices.getInfo.restore();
                    qacServices.cucardasToHtmlList.restore();
                    qacServices.projectNameToHtmlLink.restore();
                    qacServices.projectActionButtons.restore();
                    qacServices.sortProjects.restore();
                    fs.readFile.restore();
                    qacServices.user = null;
                }).then(done,done);
            });
        }
        checkGetOrg('simple organization page', html.table([
            html.tr([ html.th('project'), html.th({colspan:10},'cucardas') ]),
            html.tr([ html.td("link: simple,uno"), html.td( ["list: [qa-control][issues] cu-uno"]), html.td("b:simple:uno") ]),
            html.tr([ html.td("link: simple,dos"), html.td( ["list: [qa-control][issues] cu-dos"]), html.td("b:simple:dos") ]),
        ]));
        checkGetOrg('simple organization page authenticated',
            html.form({method:'post', action:qacServices.rootUrl},
                [html.table([
                    html.tr([ html.th('project'), html.th({colspan:10},'cucardas'), html.th({colspan:4},'actions') ]),
                    html.tr([ html.td("link: simple,uno"), html.td( ["list: [qa-control][issues] cu-uno"]), html.td("b:simple:uno") ]),
                    html.tr([ html.td("link: simple,dos"), html.td( ["list: [qa-control][issues] cu-dos"]), html.td("b:simple:dos") ]),
                    html.tr([ html.td({colspan:16, align:'right'}, [
                                html.input({type:'hidden', name:'action', value:'add'}),
                                html.input({type:'hidden', name:'organization', value:'simple'}),
                                html.input({type:'text', name:'project'}),
                                html.input({type:'submit', value:'New project...' })
                                ])
                            ])
                ])]
            ),
            true
        );
    });
    describe('project page',function() {
        function checkGetProj(msg, result, userLogged) {
            it(msg, function(done) {
                sinon.stub(qacServices, "getInfo", function(organization, project){
                    if(project !=='uno'){
                        throw new Error("unexpected project name in getInfo");
                    }
                    if(organization!=='simple'){
                        throw new Error("wrong organization name in getInfo");
                    }
                    return Promises.resolve({
                        organization:{
                            projects:[{
                                projectName:'uno'
                            },{
                                projectName:'dos'
                            }],
                            path:'the-org-path',
                            name:organization
                        },
                        project:{
                            path:'the-proj-path',
                            name:project
                        }
                    });
                });
                sinon.stub(fs, 'readFile', function(nameCucardas){
                    //console.log("nameCucardas", nameCucardas);
                    switch(nameCucardas){
                        case Path.normalize('the-org-path/projects/uno/result/cucardas.md'): return Promises.resolve('[qa-control][issues] cu-uno');
                        default: throw new Error('unexpected params in readFile of cucardas');
                    }
                });
                sinon.stub(qacServices, "cucardasToHtmlList", function(x){
                    return [html.td("list: "+x)];
                });
                sinon.stub(qacServices, "projectActionButtons", function(orga, proj){
                    return [html.td("b:"+orga+':'+proj)];
                });
                sinon.stub(qacServices, "projectNameToHtmlLink", function(orga, proj){
                    return "link: "+orga+','+proj;
                });
                sinon.stub(qacServices, "getProjectLogs", function(path) {
                   return ['qac-logs', 'bitacora-logs'];
                });
                if(userLogged) {
                    qacServices.user = 'pepe';
                }
                qacServices.getProjectPage('simple', 'uno').then(function(oHtml){
                    // console.log(oHtml.toHtmlText({pretty:true}));
                    expect(oHtml).to.eql(result);
                }).then(function(){
                    qacServices.getInfo.restore();
                    qacServices.cucardasToHtmlList.restore();
                    qacServices.projectNameToHtmlLink.restore();
                    qacServices.projectActionButtons.restore();
                    qacServices.getProjectLogs.restore();
                    fs.readFile.restore();
                    qacServices.user = null;
                }).then(done,done);
            });
        }
        checkGetProj('simple project page', html.body([
            html.table([
                html.tr([ html.th('project'), html.th({colspan:10},'cucardas') ]),
                html.tr([ html.td("link: simple,uno"), html.td( ["list: [qa-control][issues] cu-uno"]), html.td("b:simple:uno") ])
            ])
        ]));
        checkGetProj('simple project page authenticated', html.body([
            html.form({method:'post', action:qacServices.rootUrl},
                    [html.table(
                        [
                            html.tr([ html.th('project'), html.th({colspan:10},'cucardas'), html.th({colspan:4},'actions') ]),
                            html.tr([ html.td("link: simple,uno"), html.td( ["list: [qa-control][issues] cu-uno"]), html.td("b:simple:uno") ])
                        ])
                    ]),'qac-logs','bitacora-logs']),
            true
        );
    });
    describe('getAdmin',function() {
        function checkGetAdmin(msg, result, userLogged) {
            it(msg, function(done) {
                sinon.stub(qacServices, "getOrganizations", function(){ return Promises.resolve(['uno', 'dos']); });
                if(userLogged) {
                    qacServices.user = 'tito';
                }
                qacServices.getAdminPage().then(function(oHtml){
                    // console.log(oHtml.toHtmlText({pretty:true}));
                    // console.log(result.toHtmlText({pretty:true}));
                    expect(oHtml).to.eql(result);
                }).then(function(){
                    qacServices.getOrganizations.restore();
                    qacServices.user = null;
                }).then(done,done);
            });
        }
        checkGetAdmin('simple admin page',
                           html.table([
                                html.tr([html.th('organization')]),
                                html.tr([html.td([html.a({href:'/uno'}, 'uno')])]),
                                html.tr([html.td([html.a({href:'/dos'}, 'dos')])])
                                ]));
        checkGetAdmin('simple admin page authenticated',
                    html.form({method:'post', action:qacServices.rootUrl},
                        [html.table(
                            [
                                html.tr([html.th('organization'), html.th('actions')]),

                                html.tr([html.td([html.a({href:'/uno'}, 'uno')]),
                                         html.td({class:'centrado'}, [html.a({href:'/ask/delete/uno', 'codenautas-confirm':'row'},
                                                         [html.img({src:'/delete.png', alg:'del', style:'height:18px'})])
                                                 ])
                                        ]),
                                html.tr([html.td([html.a({href:'/dos'}, 'dos')]),
                                         html.td({class:'centrado'}, [html.a({href:'/ask/delete/dos', 'codenautas-confirm':'row'},
                                                         [html.img({src:'/delete.png', alg:'del', style:'height:18px'})])
                                                 ])
                                        ]),
                                html.tr([
                                        html.td({colspan:2, align:'right'},[
                                                    html.input({type:'hidden', name:'action', value:'create'}),
                                                    html.input({type:'text', name:'organization'}),
                                                    html.input({type:'submit', value:'New organization...'})
                                                ])
                                        ])

                            ])
                        ]),
                    true);
    });
});
<commit_msg>Coverage: getAdminPage()<commit_after>"use strict";
/*jshint eqnull:true */
/*jshint globalstrict:true */
/*jshint node:true */
/* global describe */
/* global it */

var expect = require('expect.js');
var sinon = require('sinon');
var Promises = require('best-promise');
var qacServices = require('../lib/qac-services.js');
var fs = require('fs-promise');
var helper=require('../test/test-helper.js');
var html = require('js-to-html').html;
var Path = require('path');
helper.setup(qacServices);

describe("qac-services overview",function(){
    it("get cucardasToHtmlList",function(){
        var obt=qacServices.cucardasToHtmlList(
            "[![npm-version](https://img.shields.io/npm/v/multilang.svg)](https://npmjs.org/package/multilang)  \n\r "+
            "[![downloads](https://img.shields.io/npm/dm/multilang.svg)](https://npmjs.org/package/multilangx) "+
            "![extending](https://img.shields.io/badge/stability-extending-orange.svg)"+
            "![stable](https://img.shields.io/badge/stability-stable-green.svg)"+
            "![otra](https://img.shields.io/badge/stability-otra-green.svg)"+
            "![otra-mas](https://img.shields.io/badge/stability-otra-mas-green.svg)"
        );
        //console.log("obt", obt);
        expect(obt).to.eql([
            html.td({class:'centrado'}, [
                html.img({src:"https://img.shields.io/badge/stability-extending-orange.svg", alt:"extending"}),
                html.img({src:"https://img.shields.io/badge/stability-stable-green.svg", alt:"stable"})
            ]),
            html.td({class:'centrado'}, [
                html.a(
                    {href:"https://npmjs.org/package/multilang"},
                    [ html.img({src:"https://img.shields.io/npm/v/multilang.svg", alt:"npm-version"}) ]
                ),
            ]),
            html.td({class:'centrado'}, [
                html.a(
                    {href:"https://npmjs.org/package/multilangx"},
                    [ html.img({src:"https://img.shields.io/npm/dm/multilang.svg", alt:"downloads"}) ]
                ),
            ]),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}),
            html.td({class:'centrado'}, [
                html.img({src:"https://img.shields.io/badge/stability-otra-green.svg", alt:"otra"}),
                html.img({src:"https://img.shields.io/badge/stability-otra-mas-green.svg", alt:"otra-mas"})
            ])
        ]);
    });
    it("get projectNameToHtmlLink",function(){
        var oriUrl = qacServices.rootUrl;
        qacServices.rootUrl='/root/'
        var obt=qacServices.projectNameToHtmlLink('simple-org','proj-name');
        expect(obt).to.eql(
            html.a({href:"/root/simple-org/proj-name"}, "proj-name")
        );
        qacServices.rootUrl = oriUrl;
    });
    it("get projectActionButtons",function(){
        var oriUrl = qacServices.rootUrl;
        qacServices.rootUrl='/root/';
        qacServices.user='user-name';
        qacServices.production=false;
        var obt=qacServices.projectActionButtons('simple-org','proj-name');
        expect(obt).to.eql([
            html.td([
                html.a({
                    href: '/root/ask/delete/simple-org/proj-name',
                    'codenautas-confirm': 'row'
                },[html.img({src:'/delete.png', alg:'del', style:'height:18px'})])
            ]),
            html.td([
                html.a({
                    href:'/root/manual-push/simple-org/proj-name'
                }, [html.img({src:'/refresh.png', alt:'rfrsh', style:'height:18px'})])
            ])
        ]);
        qacServices.production=true;
        qacServices.user=false;
        qacServices.rootUrl = oriUrl;
    });
    describe('organization page',function() {
        function checkGetOrg(msg, result, userLogged) {
            it(msg, function(done) {
                sinon.stub(qacServices, "getInfo", function(organization, project){
                    if(!!project){
                        throw new Error("unexpected project name in getInfo");
                    }
                    if(organization!=='simple'){
                        throw new Error("wrong organization name in getInfo");
                    }
                    return Promises.resolve({
                        organization:{
                            projects:[{
                                projectName:'uno'
                            },{
                                projectName:'dos'
                            }],
                            path:'the-org-path',
                            name:organization
                        }
                    });
                });
                sinon.stub(fs, 'readFile', function(nameCucardas){
                    //console.log("nameCucardas", nameCucardas);
                    switch(nameCucardas){
                        case Path.normalize('the-org-path/projects/uno/result/cucardas.md'): return Promises.resolve('[qa-control][issues] cu-uno');
                        case Path.normalize('the-org-path/projects/dos/result/cucardas.md'): return Promises.resolve('[qa-control][issues] cu-dos');
                        default: throw new Error('unexpected params in readFile of cucardas');
                    }
                });
                sinon.stub(qacServices, "cucardasToHtmlList", function(x){
                    return [html.td("list: "+x)];
                });
                sinon.stub(qacServices, "projectActionButtons", function(orga, proj){
                    return [html.td("b:"+orga+':'+proj)];
                });
                sinon.stub(qacServices, "projectNameToHtmlLink", function(orga, proj){
                    return "link: "+orga+','+proj;
                });
                sinon.stub(qacServices, "sortProjects", function(proj1, proj2) {
                   if(proj1 < proj2) {
                       return -1;
                   } else if(proj1 > proj2) {
                       return 1;
                   }
                   return 0;
                });
                if(userLogged) {
                    qacServices.user = 'pepe';
                }
                qacServices.getOrganizationPage('simple').then(function(oHtml){
                    //console.log(oHtml.toHtmlText({pretty:true}));
                    expect(oHtml).to.eql(result);
                }).then(function(){
                    qacServices.getInfo.restore();
                    qacServices.cucardasToHtmlList.restore();
                    qacServices.projectNameToHtmlLink.restore();
                    qacServices.projectActionButtons.restore();
                    qacServices.sortProjects.restore();
                    fs.readFile.restore();
                    qacServices.user = null;
                }).then(done,done);
            });
        }
        checkGetOrg('simple organization page', html.table([
            html.tr([ html.th('project'), html.th({colspan:10},'cucardas') ]),
            html.tr([ html.td("link: simple,uno"), html.td( ["list: [qa-control][issues] cu-uno"]), html.td("b:simple:uno") ]),
            html.tr([ html.td("link: simple,dos"), html.td( ["list: [qa-control][issues] cu-dos"]), html.td("b:simple:dos") ]),
        ]));
        checkGetOrg('simple organization page authenticated',
            html.form({method:'post', action:qacServices.rootUrl},
                [html.table([
                    html.tr([ html.th('project'), html.th({colspan:10},'cucardas'), html.th({colspan:4},'actions') ]),
                    html.tr([ html.td("link: simple,uno"), html.td( ["list: [qa-control][issues] cu-uno"]), html.td("b:simple:uno") ]),
                    html.tr([ html.td("link: simple,dos"), html.td( ["list: [qa-control][issues] cu-dos"]), html.td("b:simple:dos") ]),
                    html.tr([ html.td({colspan:16, align:'right'}, [
                                html.input({type:'hidden', name:'action', value:'add'}),
                                html.input({type:'hidden', name:'organization', value:'simple'}),
                                html.input({type:'text', name:'project'}),
                                html.input({type:'submit', value:'New project...' })
                                ])
                            ])
                ])]
            ),
            true
        );
    });
    describe('project page',function() {
        function checkGetProj(msg, result, userLogged) {
            it(msg, function(done) {
                sinon.stub(qacServices, "getInfo", function(organization, project){
                    if(project !=='uno'){
                        throw new Error("unexpected project name in getInfo");
                    }
                    if(organization!=='simple'){
                        throw new Error("wrong organization name in getInfo");
                    }
                    return Promises.resolve({
                        organization:{
                            projects:[{
                                projectName:'uno'
                            },{
                                projectName:'dos'
                            }],
                            path:'the-org-path',
                            name:organization
                        },
                        project:{
                            path:'the-proj-path',
                            name:project
                        }
                    });
                });
                sinon.stub(fs, 'readFile', function(nameCucardas){
                    //console.log("nameCucardas", nameCucardas);
                    switch(nameCucardas){
                        case Path.normalize('the-org-path/projects/uno/result/cucardas.md'): return Promises.resolve('[qa-control][issues] cu-uno');
                        default: throw new Error('unexpected params in readFile of cucardas');
                    }
                });
                sinon.stub(qacServices, "cucardasToHtmlList", function(x){
                    return [html.td("list: "+x)];
                });
                sinon.stub(qacServices, "projectActionButtons", function(orga, proj){
                    return [html.td("b:"+orga+':'+proj)];
                });
                sinon.stub(qacServices, "projectNameToHtmlLink", function(orga, proj){
                    return "link: "+orga+','+proj;
                });
                sinon.stub(qacServices, "getProjectLogs", function(path) {
                   return ['qac-logs', 'bitacora-logs'];
                });
                if(userLogged) {
                    qacServices.user = 'pepe';
                }
                qacServices.getProjectPage('simple', 'uno').then(function(oHtml){
                    // console.log(oHtml.toHtmlText({pretty:true}));
                    expect(oHtml).to.eql(result);
                }).then(function(){
                    qacServices.getInfo.restore();
                    qacServices.cucardasToHtmlList.restore();
                    qacServices.projectNameToHtmlLink.restore();
                    qacServices.projectActionButtons.restore();
                    qacServices.getProjectLogs.restore();
                    fs.readFile.restore();
                    qacServices.user = null;
                }).then(done,done);
            });
        }
        checkGetProj('simple project page', html.body([
            html.table([
                html.tr([ html.th('project'), html.th({colspan:10},'cucardas') ]),
                html.tr([ html.td("link: simple,uno"), html.td( ["list: [qa-control][issues] cu-uno"]), html.td("b:simple:uno") ])
            ])
        ]));
        checkGetProj('simple project page authenticated', html.body([
            html.form({method:'post', action:qacServices.rootUrl},
                    [html.table(
                        [
                            html.tr([ html.th('project'), html.th({colspan:10},'cucardas'), html.th({colspan:4},'actions') ]),
                            html.tr([ html.td("link: simple,uno"), html.td( ["list: [qa-control][issues] cu-uno"]), html.td("b:simple:uno") ])
                        ])
                    ]),'qac-logs','bitacora-logs']),
            true
        );
    });
    describe('getAdmin',function() {
        function checkGetAdmin(msg, result, userLogged, returnNoOrgs) {
            it(msg, function(done) {
                sinon.stub(qacServices, "getOrganizations", function(){ return Promises.resolve(returnNoOrgs ? [] : ['uno', 'dos']); });
                if(userLogged) {
                    qacServices.user = 'tito';
                }
                qacServices.getAdminPage().then(function(oHtml){
                    // console.log(oHtml.toHtmlText({pretty:true}));
                    // console.log(result.toHtmlText({pretty:true}));
                    expect(oHtml).to.eql(result);
                }).then(function(){
                    qacServices.getOrganizations.restore();
                    qacServices.user = null;
                }).then(done,done);
            });
        }
        checkGetAdmin('simple admin page',
                           html.table([
                                html.tr([html.th('organization')]),
                                html.tr([html.td([html.a({href:'/uno'}, 'uno')])]),
                                html.tr([html.td([html.a({href:'/dos'}, 'dos')])])
                                ]));
        checkGetAdmin('simple admin page authenticated',
                    html.form({method:'post', action:qacServices.rootUrl},
                        [html.table(
                            [
                                html.tr([html.th('organization'), html.th('actions')]),

                                html.tr([html.td([html.a({href:'/uno'}, 'uno')]),
                                         html.td({class:'centrado'}, [html.a({href:'/ask/delete/uno', 'codenautas-confirm':'row'},
                                                         [html.img({src:'/delete.png', alg:'del', style:'height:18px'})])
                                                 ])
                                        ]),
                                html.tr([html.td([html.a({href:'/dos'}, 'dos')]),
                                         html.td({class:'centrado'}, [html.a({href:'/ask/delete/dos', 'codenautas-confirm':'row'},
                                                         [html.img({src:'/delete.png', alg:'del', style:'height:18px'})])
                                                 ])
                                        ]),
                                html.tr([
                                        html.td({colspan:2, align:'right'},[
                                                    html.input({type:'hidden', name:'action', value:'create'}),
                                                    html.input({type:'text', name:'organization'}),
                                                    html.input({type:'submit', value:'New organization...'})
                                                ])
                                        ])

                            ])
                        ]),
                    true);
        checkGetAdmin('simple admin with no organizaions',
                           html.table([
                                html.tr([html.td('There are no organizations')])
                                ]), false, true);
    });
});
<|endoftext|>


<commit_before>var selftest = require('../selftest.js');
var path = require('path');
var fs = require('fs');
var _ = require('underscore');
var config = require("../config.js");
var catalogRemote = require("../catalog-remote.js");
var buildmessage = require("../buildmessage.js");
var Sandbox = selftest.Sandbox;

var getCatalog = function (sandbox) {
  var dataFile = config.getPackageStorage({ root: sandbox.warehouse });
  var catalog = new catalogRemote.RemoteCatalog();
  catalog.initialize( {packageStorage: dataFile});
  return catalog;
};

var setBanner = function (sandbox, version, banner) {
  var messages = buildmessage.capture(function () {
    var catalog = getCatalog(sandbox);
    var release = catalog.getReleaseVersion("METEOR", version);
    release.banner = { text: banner, lastUpdated: new Date };
    catalog._insertReleaseVersions([release]); //This is a hack
  });
};

var recommend = function (sandbox, version) {
  var messages = buildmessage.capture(function () {
    var catalog = getCatalog(sandbox);
    var release = catalog.getReleaseVersion('METEOR', version);
    release.recommended = true;
    catalog._insertReleaseVersions([release]);
  });
};

selftest.define("autoupdate", ['checkout'], function () {
  var s = new Sandbox({
    warehouse: {
      v1: { recommended: true},
      v2: { recommended: true },
      v3: { },
      v4: { }
    }
  });
  var run;

  // These tests involve running an app, but only because we want to
  // exercise the autoupdater, not because we actually care if the app
  // manages to run. So stop mongo from starting so that it goes faster.
  s.set("MONGO_URL", "whatever");

  // This makes packages not depend on meteor (specifically, makes our empty
  // control program not depend on meteor).
  s.set("NO_METEOR_PACKAGE", "t");

  s.createApp('myapp', 'packageless');
  s.cd('myapp', function () {
    setBanner(s, "v2", "=> New hotness v2 being downloaded.\n");
    s.write('.meteor/release', 'METEOR@v2');

    // console.log("WE ARE READY NOW", s.warehouse, s.cwd)
    // require('../utils.js').sleepMs(1000*10000)

    // Run it and see the banner for the current version.
    run = s.run("--port", "21000");
    run.waitSecs(5);
    run.match("New hotness v2 being downloaded");
    run.match("running at");
    run.stop();

    // We won't see the banner a second time, or any other message about
    // updating since we are at the latest recommended release.
    run = s.run("--port", "21000");
    run.waitSecs(5);
    run.match("running at");
    run.forbidAll("hotness");
    run.forbidAll("meteor update");
    run.stop();

    // If we are not at the latest version of Meteor, at startup, we get a
    // boring prompt to update (not a banner since we didn't set one for v1).
    s.write('.meteor/release', 'METEOR@v1');

    // We don't see any information if we run a simple command like list.
    run = s.run("list");
    run.forbidAll("New hotness v2 being downloaded");
    run.expectExit(0);
    run.stop();

    run = s.run("--version");
    run.read("Meteor v1\n");
    run.expectEnd();
    run.expectExit(0);

    // We do see a boring prompt though.
    run = s.run("--port", "22000");
    run.waitSecs(5);
    run.match("v2");
    run.forbidAll("hotness");
    run.match("meteor update");
    run.stop();

    // .. unless we explicitly forced this release. Then, no prompt.
    s.write('.meteor/release', 'METEOR@somethingelse');
    run = s.run("--release", "v1", "--port", "23000");
    run.waitSecs(5);
    run.match("running at");
    run.forbidAll("hotness");
    run.forbidAll("meteor update");
    run.stop();

    // XXX figure out about the UI of being offline. the old warehouse
    //     banner code actually printed out that it was downloading stuff,
    //     not just that it was available. we aren't quite as subtle now.

    // // OK, now say there actually is a new version available. (Use a
    // // version that we will fail to download, just so we have a chance
    // // to see what it happens if we restart before the download
    // // finishes)
    // s.write('.meteor/release', 'v2');
    // s.set('METEOR_TEST_FAIL_RELEASE_DOWNLOAD', 'offline');
    // setManifest(s, "test-junk", "=> New hotness test-junk being downloaded.\n");
    // run = s.run("--port", "24000");
    // run.match("New hotness test-junk");
    // run.stop();

    // // But we only print the banner once.
    // run = s.run("--port", "25000");
    // run.match("Meteor test-junk is being downloaded");
    // run.stop();
    // run.forbidAll("hotness");

    // OK, now use a version that we already have, so that the update
    // will succeed (we don't currently have facilities for stubbing out
    // the release download itself, but that's OK -- the updater only
    // checks if our latest version is not equal to the one in the
    // manifest, not if we actually have the version in the manifest;
    // and the downloading code turns out to be a noop if we already
    // have that version).
    recommend(s, "v3");
    s.write('.meteor/release', 'METEOR@v2');
    run = s.run("--port", "26000");
    run.match("Meteor v3 is available");
    run.match("meteor update");
    run.stop();

    run = s.run("update");
    run.read("myapp: updated to Meteor v3.");
    run.match("Your packages are at their latest compatible versions.\n");
    run.expectExit(0);

    run = s.run("--version");
    run.read("Meteor v3\n");
    run.expectEnd();
    run.expectExit(0);

    run = s.run("update");
    run.match("already at Meteor v3, the latest release");
    run.expectExit(0);

    // Update the app back to an older version.
    run = s.run("update", "--release", "v2");
    run.read("myapp: updated to Meteor v2.\n");
    run.expectEnd();
    run.expectExit(0);

    run = s.run("--version");
    run.read("Meteor v2\n");
    run.expectEnd();
    run.expectExit(0);

    run = s.run("update", "--release", "v2");
    run.match("already at Meteor v2");
    run.forbidAll("the latest release");
    run.expectExit(0);

    // Update explicitly to v3.
    run = s.run("update", "--release", "v3");
    run.read("myapp: updated to Meteor v3.\n");
    // We *don't* print "All your package dependencies are already up to date"
    // here, because we don't try to additionally update packages when you
    // request a specific release.
    run.expectEnd();
    run.expectExit(0);
  });

  // The latest version has been updated globally too.
  run = s.run("--version");
  run.read("Meteor v3\n");
  run.expectEnd();
  run.expectExit(0);

  // Recommend v4 and watch --version update.
  // XXX: Not sure if this is desired behavior.
  recommend(s, "v4");
  run = s.run("--version");
  run.match("Meteor v4\n");
  run.expectEnd();
  run.expectExit(0);

});
<commit_msg>remove unnecessary use of NO_METEOR_PACKAGE<commit_after>var selftest = require('../selftest.js');
var path = require('path');
var fs = require('fs');
var _ = require('underscore');
var config = require("../config.js");
var catalogRemote = require("../catalog-remote.js");
var buildmessage = require("../buildmessage.js");
var Sandbox = selftest.Sandbox;

var getCatalog = function (sandbox) {
  var dataFile = config.getPackageStorage({ root: sandbox.warehouse });
  var catalog = new catalogRemote.RemoteCatalog();
  catalog.initialize( {packageStorage: dataFile});
  return catalog;
};

var setBanner = function (sandbox, version, banner) {
  var messages = buildmessage.capture(function () {
    var catalog = getCatalog(sandbox);
    var release = catalog.getReleaseVersion("METEOR", version);
    release.banner = { text: banner, lastUpdated: new Date };
    catalog._insertReleaseVersions([release]); //This is a hack
  });
};

var recommend = function (sandbox, version) {
  var messages = buildmessage.capture(function () {
    var catalog = getCatalog(sandbox);
    var release = catalog.getReleaseVersion('METEOR', version);
    release.recommended = true;
    catalog._insertReleaseVersions([release]);
  });
};

selftest.define("autoupdate", ['checkout'], function () {
  var s = new Sandbox({
    warehouse: {
      v1: { recommended: true},
      v2: { recommended: true },
      v3: { },
      v4: { }
    }
  });
  var run;

  // These tests involve running an app, but only because we want to
  // exercise the autoupdater, not because we actually care if the app
  // manages to run. So stop mongo from starting so that it goes faster.
  s.set("MONGO_URL", "whatever");

  s.createApp('myapp', 'packageless');
  s.cd('myapp', function () {
    setBanner(s, "v2", "=> New hotness v2 being downloaded.\n");
    s.write('.meteor/release', 'METEOR@v2');

    // console.log("WE ARE READY NOW", s.warehouse, s.cwd)
    // require('../utils.js').sleepMs(1000*10000)

    // Run it and see the banner for the current version.
    run = s.run("--port", "21000");
    run.waitSecs(5);
    run.match("New hotness v2 being downloaded");
    run.match("running at");
    run.stop();

    // We won't see the banner a second time, or any other message about
    // updating since we are at the latest recommended release.
    run = s.run("--port", "21000");
    run.waitSecs(5);
    run.match("running at");
    run.forbidAll("hotness");
    run.forbidAll("meteor update");
    run.stop();

    // If we are not at the latest version of Meteor, at startup, we get a
    // boring prompt to update (not a banner since we didn't set one for v1).
    s.write('.meteor/release', 'METEOR@v1');

    // We don't see any information if we run a simple command like list.
    run = s.run("list");
    run.forbidAll("New hotness v2 being downloaded");
    run.expectExit(0);
    run.stop();

    run = s.run("--version");
    run.read("Meteor v1\n");
    run.expectEnd();
    run.expectExit(0);

    // We do see a boring prompt though.
    run = s.run("--port", "22000");
    run.waitSecs(5);
    run.match("v2");
    run.forbidAll("hotness");
    run.match("meteor update");
    run.stop();

    // .. unless we explicitly forced this release. Then, no prompt.
    s.write('.meteor/release', 'METEOR@somethingelse');
    run = s.run("--release", "v1", "--port", "23000");
    run.waitSecs(5);
    run.match("running at");
    run.forbidAll("hotness");
    run.forbidAll("meteor update");
    run.stop();

    // XXX figure out about the UI of being offline. the old warehouse
    //     banner code actually printed out that it was downloading stuff,
    //     not just that it was available. we aren't quite as subtle now.

    // // OK, now say there actually is a new version available. (Use a
    // // version that we will fail to download, just so we have a chance
    // // to see what it happens if we restart before the download
    // // finishes)
    // s.write('.meteor/release', 'v2');
    // s.set('METEOR_TEST_FAIL_RELEASE_DOWNLOAD', 'offline');
    // setManifest(s, "test-junk", "=> New hotness test-junk being downloaded.\n");
    // run = s.run("--port", "24000");
    // run.match("New hotness test-junk");
    // run.stop();

    // // But we only print the banner once.
    // run = s.run("--port", "25000");
    // run.match("Meteor test-junk is being downloaded");
    // run.stop();
    // run.forbidAll("hotness");

    // OK, now use a version that we already have, so that the update
    // will succeed (we don't currently have facilities for stubbing out
    // the release download itself, but that's OK -- the updater only
    // checks if our latest version is not equal to the one in the
    // manifest, not if we actually have the version in the manifest;
    // and the downloading code turns out to be a noop if we already
    // have that version).
    recommend(s, "v3");
    s.write('.meteor/release', 'METEOR@v2');
    run = s.run("--port", "26000");
    run.match("Meteor v3 is available");
    run.match("meteor update");
    run.stop();

    run = s.run("update");
    run.read("myapp: updated to Meteor v3.");
    run.match("Your packages are at their latest compatible versions.\n");
    run.expectExit(0);

    run = s.run("--version");
    run.read("Meteor v3\n");
    run.expectEnd();
    run.expectExit(0);

    run = s.run("update");
    run.match("already at Meteor v3, the latest release");
    run.expectExit(0);

    // Update the app back to an older version.
    run = s.run("update", "--release", "v2");
    run.read("myapp: updated to Meteor v2.\n");
    run.expectEnd();
    run.expectExit(0);

    run = s.run("--version");
    run.read("Meteor v2\n");
    run.expectEnd();
    run.expectExit(0);

    run = s.run("update", "--release", "v2");
    run.match("already at Meteor v2");
    run.forbidAll("the latest release");
    run.expectExit(0);

    // Update explicitly to v3.
    run = s.run("update", "--release", "v3");
    run.read("myapp: updated to Meteor v3.\n");
    // We *don't* print "All your package dependencies are already up to date"
    // here, because we don't try to additionally update packages when you
    // request a specific release.
    run.expectEnd();
    run.expectExit(0);
  });

  // The latest version has been updated globally too.
  run = s.run("--version");
  run.read("Meteor v3\n");
  run.expectEnd();
  run.expectExit(0);

  // Recommend v4 and watch --version update.
  // XXX: Not sure if this is desired behavior.
  recommend(s, "v4");
  run = s.run("--version");
  run.match("Meteor v4\n");
  run.expectEnd();
  run.expectExit(0);

});
<|endoftext|>


<commit_before>/*
 * NTwitBot - util.test.js
 * Copyright (C) 2016-2017 Jordan Sne
 *
 * 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 3 of the License, or
 * (at your option) any later version.
 *
 * 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/>.
 */

const Util = require('../../lib/util.js');
const utils = new Util();

describe('Util', () => {
    it('should capitalize words', () => {
        expect(utils.capitalize('test')).toBe('Test');
        expect(utils.capitalize('Test')).toBe('Test');
        expect(utils.capitalize('#test')).toBe('#test');
    });

    it('should check capitalization of chars', () => {
        expect(utils.isUpperCase('t')).toBe(false);
        expect(utils.isUpperCase('T')).toBe(true);
    });

    it('should check if an object is in an array', () => {
        const someObject = { 'id': 2322 };
        const otherObject1 = { 'id': 3232 };
        const otherObject2 = { 'id': 4322 };

        const array1 = [someObject, otherObject1];
        const array2 = [otherObject1, otherObject2];

        expect(utils.isInArray(array1, someObject)).toBe(true);
        expect(utils.isInArray(array2, someObject)).toBe(false);
    });

    it('should generate shuffled arrays', () => {
        const shuffleMock = jest.spyOn(utils, 'shuffleArray');

        expect.assertions(2);
        shuffleMock.mockImplementationOnce((array) => {
            expect(array).toEqual([ 0, 1, 2, 3 ]);
            return [2, 0, 1, 3];
        });
        expect(utils.generateShuffledArray(4)).toEqual([ 2, 0, 1, 3 ]);

        shuffleMock.mockRestore();
    });

    it('should not change any elements when shuffling an array', () => {
        const array = utils.shuffleArray([ 1, 3, 5 ]);

        expect(array).toHaveLength(3);
        expect(array).toContain(1);
        expect(array).toContain(3);
        expect(array).toContain(5);
    });

    it('should check for ending punctuation', () => {
        expect(utils.endsWithPunc('This is a test.')).toBe(true);
        expect(utils.endsWithPunc('This is a test!')).toBe(true);
        expect(utils.endsWithPunc('This is a test?')).toBe(true);
        expect(utils.endsWithPunc('This is a test')).toBe(false);
    });
});
<commit_msg>Add tests for date methods in utils<commit_after>/*
 * NTwitBot - util.test.js
 * Copyright (C) 2016-2017 Jordan Sne
 *
 * 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 3 of the License, or
 * (at your option) any later version.
 *
 * 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/>.
 */

const Util = require('../../lib/util.js');
const utils = new Util();

describe('Util', () => {
    it('should capitalize words', () => {
        expect(utils.capitalize('test')).toBe('Test');
        expect(utils.capitalize('Test')).toBe('Test');
        expect(utils.capitalize('#test')).toBe('#test');
    });

    it('should check capitalization of chars', () => {
        expect(utils.isUpperCase('t')).toBe(false);
        expect(utils.isUpperCase('T')).toBe(true);
    });

    it('should check if an object is in an array', () => {
        const someObject = { 'id': 2322 };
        const otherObject1 = { 'id': 3232 };
        const otherObject2 = { 'id': 4322 };

        const array1 = [someObject, otherObject1];
        const array2 = [otherObject1, otherObject2];

        expect(utils.isInArray(array1, someObject)).toBe(true);
        expect(utils.isInArray(array2, someObject)).toBe(false);
    });

    it('should generate shuffled arrays', () => {
        const shuffleMock = jest.spyOn(utils, 'shuffleArray');

        expect.assertions(2);
        shuffleMock.mockImplementationOnce((array) => {
            expect(array).toEqual([ 0, 1, 2, 3 ]);
            return [2, 0, 1, 3];
        });
        expect(utils.generateShuffledArray(4)).toEqual([ 2, 0, 1, 3 ]);

        shuffleMock.mockRestore();
    });

    it('should not change any elements when shuffling an array', () => {
        const array = utils.shuffleArray([ 1, 3, 5 ]);

        expect(array).toHaveLength(3);
        expect(array).toContain(1);
        expect(array).toContain(3);
        expect(array).toContain(5);
    });

    it('should check for ending punctuation', () => {
        expect(utils.endsWithPunc('This is a test.')).toBe(true);
        expect(utils.endsWithPunc('This is a test!')).toBe(true);
        expect(utils.endsWithPunc('This is a test?')).toBe(true);
        expect(utils.endsWithPunc('This is a test')).toBe(false);
    });

    describe('Date', () => {
        const Date_ = Date;

        afterAll(() => {
            global.Date = Date_;
        });

        describe('when the date has single digit time & date numbers', () => {
            beforeAll(() => {
                global.Date = jest.fn(() => new Date_(2016, 5, 3, 8, 1, 4));
            });

            it('should generate the proper int representation', () => {
                expect(utils.getTime()).toBe(201606030801);
            });

            it('should generate the proper string representation', () => {
                expect(utils.getFormattedTime()).toBe('06/03/2016 08:01:04');
            });
        });

        describe('when the date has double digit time & date numbers', () => {
            beforeAll(() => {
                global.Date = jest.fn(() => new Date_(2016, 10, 23, 13, 54, 23));
            });

            it('should generate the proper int representation', () => {
                expect(utils.getTime()).toBe(201611231354);
            });

            it('should generate the proper string representation', () => {
                expect(utils.getFormattedTime()).toBe('11/23/2016 13:54:23');
            });
        });
    });
});
<|endoftext|>


<commit_before>/**
 * Created by justin.baize on 6/16/16.
 */
var fs = require('fs');
var _  = require('lodash');

var competitorA = {
  rating: 1200,
  wins: 0,
  losses: 0
}

var competitorB = {
  rating: 1400,
  wins:   0,
  losses: 0
}

var competitorC = {
  rating: 1600,
  wins:   0,
  losses: 0
}

var competitorD = {
  rating: 1800,
  wins:   0,
  losses: 0
}

var theCompetitionMat  = []
var competitionMatOdds = []
var winnersBracket     = []
var losersBracket      = []
var firstCompetitorRating  = 0
var secondCompetitorRating = 0
var firstCompetitorsProbabilityOfVictory = 0
var secondCompetitorsProbabilityOfVictory = 0
var firstCompetitor = null
var secondCompetitor = null
var nameOfFirstCompetitor  = null
var nameOfSecondCompetitor = null

var firstCompetitorRating = null
var secondCompetitorRating = null

var k = 8
var n = 1

var arrayOfCompetitors = [{competitorA},{competitorB},{competitorC},{competitorD}]

/**
 * @name matPopulator
 * @description - Takes two competitors from arrayOfCompetitors and
 *                puts them into theCompetitionMat array.
 * @param arrayOfCompetitors
 **/

var matPopulator = function(array){

  theCompetitionMat.push(array.pop())
  theCompetitionMat.push(array.pop())

}

matPopulator(arrayOfCompetitors)

var probabilityCalculator = function(array){

  firstCompetitor  = array[0]
  secondCompetitor = array[1]
  nameOfFirstCompetitor  = Object.keys(firstCompetitor)[0]
  nameOfSecondCompetitor = Object.keys(secondCompetitor)[0]

  firstCompetitorRating  = firstCompetitor[nameOfFirstCompetitor]['rating']
  secondCompetitorRating = secondCompetitor[nameOfSecondCompetitor]['rating']

  // console.log("firstOpponent:",firstCompetitor)
  // console.log("Name of First Competitor:",nameOfFirstCompetitor)
  // console.log("secondOpponent:",secondCompetitor)
  // console.log("Name of Second Competitor:",nameOfSecondCompetitor)
  // console.log("firstCompetitorRating:",firstCompetitorRating)
  // console.log("secondCompetitorRating:",secondCompetitorRating)
}

probabilityCalculator(theCompetitionMat)

var ratingAdjustersss = function(array){
  var recordWinsForA    = firstCompetitor[nameOfFirstCompetitor]['wins']
  var recordWinsForB    = secondCompetitor[nameOfSecondCompetitor]['wins']
  var recordLossesForA  = firstCompetitor[nameOfFirstCompetitor]['losses']
  var recordLossesForB  = secondCompetitor[nameOfSecondCompetitor]['losses']

  firstCompetitorsProbabilityOfVictory = 1 / (1 + Math.pow(10, ((secondCompetitorRating - firstCompetitorRating) / 400)))
  secondCompetitorsProbabilityOfVictory = 1 / (1 + Math.pow(10, ((firstCompetitorRating - secondCompetitorRating) / 400)))

  // competitionMatOdds.push(probabilityOfVictoryForA)
  // competitionMatOdds.push(probabilityOfVictoryForB)

  // console.log("firstCompetitorsProbabilityOfVictory:", firstCompetitorsProbabilityOfVictory)
  // console.log("secondCompetitorsProbabilityOfVictory:", secondCompetitorsProbabilityOfVictory)
  // console.log("recordWinsForA:",recordWinsForA)
  // console.log("recordWinsForB:",recordWinsForB)
  // console.log("recordLossesForA:",recordLossesForA)
  // console.log("recordLossesForB:",recordLossesForB)
  //
  // console.log("theCompetitionFloor:",array)

}

ratingAdjustersss(theCompetitionMat)

var ratingsAdjuster = function(array) {

  //BEGIN step one!
  console.log("theCompetitionFloor:",array)

  // TODO: rename these next six variables!

  //END step one!

  //BEGIN step two!

  var outcomeCalculator = function (probabilityOfVictoryForA) {

    var randomNumber = Math.random()

    if ( probabilityOfVictoryForA > randomNumber ) {

      recordWinsForA++
      recordLossesForB++

      firstCompetitor[nameOfFirstCompetitor]['wins']     = recordWinsForA
      secondCompetitor[nameOfSecondCompetitor]['losses'] = recordLossesForB

    } else {

      recordLossesForA++
      recordWinsForB++

      firstCompetitor[nameOfFirstCompetitor]['losses'] = recordLossesForA
      secondCompetitor[nameOfSecondCompetitor]['wins'] = recordWinsForB

    }

    // console.log("after outcomeCalculator firstCompetitor:",firstCompetitor)
    // console.log("after outcomeCalculator secondCompetitor:",secondCompetitor)

  }

  outcomeCalculator(probabilityOfVictoryForA)
  //END step two!

  //BEGIN step three!
  var newRatingCalculator = function(array){

    // console.log("this should be the competitionMat:",array1)

    // var probabilityOfVictoryForFirst = array2[0]
    // var probabilityOfVictoryForSecond = array2[1]

    // console.log("**firstOpponent:",firstCompetitor)
    // console.log("**Name of First Competitor:",nameOfFirstCompetitor)
    // console.log("**secondOpponent:",secondCompetitor)
    // console.log("**Name of Second Competitor:",nameOfSecondCompetitor)

    // console.log("firstCompetitorRating:",firstCompetitorRating)
    // console.log("secondCompetitorRating:",secondCompetitorRating)

    var rawNewRatingForFirst = firstCompetitorRating + k*(firstCompetitor[nameOfFirstCompetitor]['wins'] - (probabilityOfVictoryForA*n))
    var rawNewRatingForSecond = secondCompetitorRating + k*(secondCompetitor[nameOfSecondCompetitor]['wins'] - (probabilityOfVictoryForB*n))

    // console.log("rawNewRatingForFirst:",rawNewRatingForFirst)
    // console.log("rawNewRatingForSecond:",rawNewRatingForSecond)

    var newRatingForFirst = Math.round(rawNewRatingForFirst)
    var newRatingForSecond = Math.round(rawNewRatingForSecond)

    // console.log("newRatingForFirst:",newRatingForFirst)
    // console.log("newRatingForSecond:",newRatingForSecond)

    firstCompetitor[nameOfFirstCompetitor]['rating']   = newRatingForFirst
    secondCompetitor[nameOfSecondCompetitor]['rating'] = newRatingForSecond

    // console.log("after the smoke has cleared:",array1)

    // if (newRating === competitorRating && competitorRating < rawNewRating ) {
    //
    //   competitor[competitorStats[0]] = newRating+1
    //
    // } else if ( newRating === competitorRating && competitorRating > rawNewRating ) {
    //
    //   competitor[competitorStats[0]] = newRating-1
    //
    // } else {
    //
    //   competitor[competitorStats[0]] = newRating
    //
    // }

    // console.log("competitor:",competitor)

  }
  newRatingCalculator(theCompetitionMat)
  //END step three!

  //BEGIN step four!
  var matEvacuator = function(array){

    // console.log("this should be the competitionFloor!:",array)

    if ( firstCompetitor[nameOfFirstCompetitor]['losses'] ) {

      // console.log("the first competitor lost!")
      winnersBracket.push(array.pop())
      losersBracket.push(array.pop())
      // console.log("winnersBracket:",winnersBracket)
      // console.log("losersBracket:",losersBracket)

    } else {

      // console.log("the second person lost!")

      losersBracket.push(array.pop())
      winnersBracket.push(array.pop())

      // console.log("losersBracket:",losersBracket)
      // console.log("winnersBracket:",winnersBracket)

      console.log("array after populating losers and winners brackets:",array)
      console.log("arrayOfCompetitors:",arrayOfCompetitors)

    }

  }
  matEvacuator(theCompetitionMat)
  //END step four!

  // working!

  // tournament(arrayOfCompetitors)

}

//working too
// ratingsAdjuster(competitorA,competitorB)

var tournament = function(array){

  // console.log("this should be the array of competitors:",array)

  // console.log("Reporting on the competition floor!:",theCompetitionMat)

  ratingsAdjuster(theCompetitionMat)

}

// tournament(arrayOfCompetitors)

// matPopulator(arrayOfCompetitors)<commit_msg>Refactored referee()<commit_after>/**
 * Created by justin.baize on 6/16/16.
 */
var fs = require('fs');
var _  = require('lodash');

var competitorA = {
  rating: 1200,
  wins: 0,
  losses: 0
}

var competitorB = {
  rating: 1400,
  wins:   0,
  losses: 0
}

var competitorC = {
  rating: 1600,
  wins:   0,
  losses: 0
}

var competitorD = {
  rating: 1800,
  wins:   0,
  losses: 0
}

var theCompetitionMat  = []
var competitionMatOdds = []
var winnersBracket     = []
var losersBracket      = []
var firstCompetitorRating  = 0
var secondCompetitorRating = 0
var firstCompetitorsProbabilityOfVictory = 0
var secondCompetitorsProbabilityOfVictory = 0
var firstCompetitor = null
var secondCompetitor = null
var nameOfFirstCompetitor  = null
var nameOfSecondCompetitor = null

var firstCompetitorRating  = null
var secondCompetitorRating = null

var recordWinsForA    = null
var recordWinsForB    = null
var recordLossesForA  = null
var recordLossesForB  = null

var k = 8
var n = 1

var arrayOfCompetitors = [{competitorA},{competitorB},{competitorC},{competitorD}]

/**
 * @name matPopulator
 * @description - Takes two competitors from arrayOfCompetitors and
 *                puts them into theCompetitionMat array.
 * @param arrayOfCompetitors
 **/

var matPopulator = function(array){

  theCompetitionMat.push(array.pop())
  theCompetitionMat.push(array.pop())

}

matPopulator(arrayOfCompetitors)

var probabilityCalculator = function(array){

  firstCompetitor  = array[0]
  secondCompetitor = array[1]
  nameOfFirstCompetitor  = Object.keys(firstCompetitor)[0]
  nameOfSecondCompetitor = Object.keys(secondCompetitor)[0]

  firstCompetitorRating  = firstCompetitor[nameOfFirstCompetitor]['rating']
  secondCompetitorRating = secondCompetitor[nameOfSecondCompetitor]['rating']

  // console.log("firstOpponent:",firstCompetitor)
  // console.log("Name of First Competitor:",nameOfFirstCompetitor)
  // console.log("secondOpponent:",secondCompetitor)
  // console.log("Name of Second Competitor:",nameOfSecondCompetitor)
  // console.log("firstCompetitorRating:",firstCompetitorRating)
  // console.log("secondCompetitorRating:",secondCompetitorRating)

  var recordWinsForA    = firstCompetitor[nameOfFirstCompetitor]['wins']
  var recordWinsForB    = secondCompetitor[nameOfSecondCompetitor]['wins']
  var recordLossesForA  = firstCompetitor[nameOfFirstCompetitor]['losses']
  var recordLossesForB  = secondCompetitor[nameOfSecondCompetitor]['losses']

  firstCompetitorsProbabilityOfVictory = 1 / (1 + Math.pow(10, ((secondCompetitorRating - firstCompetitorRating) / 400)))
  secondCompetitorsProbabilityOfVictory = 1 / (1 + Math.pow(10, ((firstCompetitorRating - secondCompetitorRating) / 400)))

  // competitionMatOdds.push(probabilityOfVictoryForA)
  // competitionMatOdds.push(probabilityOfVictoryForB)

  // console.log("firstCompetitorsProbabilityOfVictory:", firstCompetitorsProbabilityOfVictory)
  // console.log("secondCompetitorsProbabilityOfVictory:", secondCompetitorsProbabilityOfVictory)
  // console.log("recordWinsForA:",recordWinsForA)
  // console.log("recordWinsForB:",recordWinsForB)
  // console.log("recordLossesForA:",recordLossesForA)
  // console.log("recordLossesForB:",recordLossesForB)

  // console.log("theCompetitionFloor:",array)
}

probabilityCalculator(theCompetitionMat)

var referee = function(probability){

  var randomNumber = Math.random()

  if ( probability > randomNumber ) {

    recordWinsForA++
    recordLossesForB++

    firstCompetitor[nameOfFirstCompetitor]['wins']     = recordWinsForA
    secondCompetitor[nameOfSecondCompetitor]['losses'] = recordLossesForB

  } else {

    recordLossesForA++
    recordWinsForB++

    firstCompetitor[nameOfFirstCompetitor]['losses'] = recordLossesForA
    secondCompetitor[nameOfSecondCompetitor]['wins'] = recordWinsForB

  }

}

referee(firstCompetitorsProbabilityOfVictory)

console.log("theCompetitionMat:",theCompetitionMat)

var ratingsAdjuster = function(array) {

  //BEGIN step one!
  console.log("theCompetitionFloor:",array)

  // TODO: rename these next six variables!

  //END step one!

  //BEGIN step two!

  var outcomeCalculator = function (probabilityOfVictoryForA) {

    // var randomNumber = Math.random()

    if ( probabilityOfVictoryForA > randomNumber ) {

      recordWinsForA++
      recordLossesForB++

      firstCompetitor[nameOfFirstCompetitor]['wins']     = recordWinsForA
      secondCompetitor[nameOfSecondCompetitor]['losses'] = recordLossesForB

    } else {

      recordLossesForA++
      recordWinsForB++

      firstCompetitor[nameOfFirstCompetitor]['losses'] = recordLossesForA
      secondCompetitor[nameOfSecondCompetitor]['wins'] = recordWinsForB

    }

    // console.log("after outcomeCalculator firstCompetitor:",firstCompetitor)
    // console.log("after outcomeCalculator secondCompetitor:",secondCompetitor)

  }

  outcomeCalculator(probabilityOfVictoryForA)
  //END step two!

  //BEGIN step three!
  var newRatingCalculator = function(array){

    // console.log("this should be the competitionMat:",array1)

    // var probabilityOfVictoryForFirst = array2[0]
    // var probabilityOfVictoryForSecond = array2[1]

    // console.log("**firstOpponent:",firstCompetitor)
    // console.log("**Name of First Competitor:",nameOfFirstCompetitor)
    // console.log("**secondOpponent:",secondCompetitor)
    // console.log("**Name of Second Competitor:",nameOfSecondCompetitor)

    // console.log("firstCompetitorRating:",firstCompetitorRating)
    // console.log("secondCompetitorRating:",secondCompetitorRating)

    var rawNewRatingForFirst = firstCompetitorRating + k*(firstCompetitor[nameOfFirstCompetitor]['wins'] - (probabilityOfVictoryForA*n))
    var rawNewRatingForSecond = secondCompetitorRating + k*(secondCompetitor[nameOfSecondCompetitor]['wins'] - (probabilityOfVictoryForB*n))

    // console.log("rawNewRatingForFirst:",rawNewRatingForFirst)
    // console.log("rawNewRatingForSecond:",rawNewRatingForSecond)

    var newRatingForFirst = Math.round(rawNewRatingForFirst)
    var newRatingForSecond = Math.round(rawNewRatingForSecond)

    // console.log("newRatingForFirst:",newRatingForFirst)
    // console.log("newRatingForSecond:",newRatingForSecond)

    firstCompetitor[nameOfFirstCompetitor]['rating']   = newRatingForFirst
    secondCompetitor[nameOfSecondCompetitor]['rating'] = newRatingForSecond

    // console.log("after the smoke has cleared:",array1)

    // if (newRating === competitorRating && competitorRating < rawNewRating ) {
    //
    //   competitor[competitorStats[0]] = newRating+1
    //
    // } else if ( newRating === competitorRating && competitorRating > rawNewRating ) {
    //
    //   competitor[competitorStats[0]] = newRating-1
    //
    // } else {
    //
    //   competitor[competitorStats[0]] = newRating
    //
    // }

    // console.log("competitor:",competitor)

  }
  newRatingCalculator(theCompetitionMat)
  //END step three!

  //BEGIN step four!
  var matEvacuator = function(array){

    // console.log("this should be the competitionFloor!:",array)

    if ( firstCompetitor[nameOfFirstCompetitor]['losses'] ) {

      // console.log("the first competitor lost!")
      winnersBracket.push(array.pop())
      losersBracket.push(array.pop())
      // console.log("winnersBracket:",winnersBracket)
      // console.log("losersBracket:",losersBracket)

    } else {

      // console.log("the second person lost!")

      losersBracket.push(array.pop())
      winnersBracket.push(array.pop())

      // console.log("losersBracket:",losersBracket)
      // console.log("winnersBracket:",winnersBracket)

      console.log("array after populating losers and winners brackets:",array)
      console.log("arrayOfCompetitors:",arrayOfCompetitors)

    }

  }
  matEvacuator(theCompetitionMat)
  //END step four!

  // working!

  // tournament(arrayOfCompetitors)

}

//working too
// ratingsAdjuster(competitorA,competitorB)

var tournament = function(array){

  // console.log("this should be the array of competitors:",array)

  // console.log("Reporting on the competition floor!:",theCompetitionMat)

  ratingsAdjuster(theCompetitionMat)

}

// tournament(arrayOfCompetitors)

// matPopulator(arrayOfCompetitors)<|endoftext|>