<commit_before>(function($) {

  $.fn.tweet = function(o){
    var s = {
      username: ["seaofclouds"],              // [string]   required, unless you want to display our tweets. :) it can be an array, just do ["username1","username2","etc"]
      list: null,                              //[string]   optional name of list belonging to username
      avatar_size: null,                      // [integer]  height and width of avatar if displayed (48px max)
      count: 3,                               // [integer]  how many tweets to display?
      intro_text: null,                       // [string]   do you want text BEFORE your your tweets?
      outro_text: null,                       // [string]   do you want text AFTER your tweets?
      join_text:  null,                       // [string]   optional text in between date and tweet, try setting to "auto"
      auto_join_text_default: "i said,",      // [string]   auto text for non verb: "i said" bullocks
      auto_join_text_ed: "i",                 // [string]   auto text for past tense: "i" surfed
      auto_join_text_ing: "i am",             // [string]   auto tense for present tense: "i was" surfing
      auto_join_text_reply: "i replied to",   // [string]   auto tense for replies: "i replied to" @someone "with"
      auto_join_text_url: "i was looking at", // [string]   auto tense for urls: "i was looking at" http:...
      loading_text: null,                     // [string]   optional loading text, displayed while tweets load
      query: null                             // [string]   optional search query
    };

    if(o) $.extend(s, o);

    $.fn.extend({
      linkUrl: function() {
        var returning = [];
        var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi;
        this.each(function() {
          returning.push(this.replace(regexp,"$1"));
        });
        return $(returning);
      },
      linkUser: function() {
        var returning = [];
        var regexp = /[\@]+([A-Za-z0-9-_]+)/gi;
        this.each(function() {
          returning.push(this.replace(regexp,"@$1"));
        });
        return $(returning);
      },
      linkHash: function() {
        var returning = [];
        var regexp = /(?:^| )[\#]+([A-Za-z0-9-_]+)/gi;
        this.each(function() {
          returning.push(this.replace(regexp, ' #$1'));
        });
        return $(returning);
      },
      capAwesome: function() {
        var returning = [];
        this.each(function() {
          returning.push(this.replace(/\b(awesome)\b/gi, '$1'));
        });
        return $(returning);
      },
      capEpic: function() {
        var returning = [];
        this.each(function() {
          returning.push(this.replace(/\b(epic)\b/gi, '$1'));
        });
        return $(returning);
      },
      makeHeart: function() {
        var returning = [];
        this.each(function() {
          returning.push(this.replace(/(<)+[3]/gi, "<tt class='heart'>♥</tt>"));
        });
        return $(returning);
      }
    });

    function parse_date(date_str) {
      // The non-search twitter APIs return inconsistently-formatted dates, which Date.parse
      // cannot handle in IE. We therefore perform the following transformation:
      // "Wed Apr 29 08:53:31 +0000 2009" => "Wed, Apr 29 2009 08:53:31 +0000"
      return Date.parse(date_str.replace(/^([a-z]{3})( [a-z]{3} \d\d?)(.*)( \d{4})$/i, '$1,$2$4$3'));
    }

    function relative_time(time_value) {
      var parsed_date = parse_date(time_value);
      var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
      var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
      var pluralize = function (singular, n) {
        return '' + n + ' ' + singular + (n == 1 ? '' : 's');
      };
      if(delta < 60) {
      return 'less than a minute ago';
      } else if(delta < (60*60)) {
      return 'about ' + pluralize("minute", parseInt(delta / 60)) + ' ago';
      } else if(delta < (24*60*60)) {
      return 'about ' + pluralize("hour", parseInt(delta / 3600)) + ' ago';
      } else {
      return 'about ' + pluralize("day", parseInt(delta / 86400)) + ' ago';
      }
    }

    function build_url() {
      var proto = ('https:' == document.location.protocol ? 'https:' : 'http:');
      if (s.list) {
        return proto+"//api.twitter.com/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+s.count+"&callback=?";
      } else if (s.query == null && s.username.length == 1) {
        return proto+'//api.twitter.com/1/statuses/user_timeline.json?screen_name='+s.username[0]+'&count='+s.count+'&include_rts=1&callback=?';
      } else {
        var query = (s.query || 'from:'+s.username.join(' OR from:'));
        return proto+'//search.twitter.com/search.json?&q='+encodeURIComponent(query)+'&rpp='+s.count+'&callback=?';
      }
    }

    return this.each(function(i, widget){
      var list = $('
').appendTo(widget);
      var intro = '
'+s.intro_text+'
';
      var outro = '
'+s.outro_text+'
';
      var loading = $('
'+s.loading_text+'
');

      if(typeof(s.username) == "string"){
        s.username = [s.username];
      }

      if (s.loading_text) $(widget).append(loading);
      $.getJSON(build_url(), function(data){
        if (s.loading_text) loading.remove();
        if (s.intro_text) list.before(intro);
        var tweets = (data.results || data);
        $.each(tweets, function(i,item){
          // auto join text based on verb tense and content
          if (s.join_text == "auto") {
            if (item.text.match(/^(@([A-Za-z0-9-_]+)) .*/i)) {
              var join_text = s.auto_join_text_reply;
            } else if (item.text.match(/(^\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+) .*/i)) {
              var join_text = s.auto_join_text_url;
            } else if (item.text.match(/^((\w+ed)|just) .*/im)) {
              var join_text = s.auto_join_text_ed;
            } else if (item.text.match(/^(\w*ing) .*/i)) {
              var join_text = s.auto_join_text_ing;
            } else {
              var join_text = s.auto_join_text_default;
            }
          } else {
            var join_text = s.join_text;
          };

          var from_user = item.from_user || item.user.screen_name;
          var profile_image_url = item.profile_image_url || item.user.profile_image_url;
          var join_template = ' '+join_text+' ';
          var join = ((s.join_text) ? join_template : ' ');
          var avatar_template = '';
          var avatar = (s.avatar_size ? avatar_template : '');
          var date = ''+relative_time(item.created_at)+'';
          var text = '' +$([item.text]).linkUrl().linkUser().linkHash().makeHeart().capAwesome().capEpic()[0]+ '';

          // until we create a template option, arrange the items below to alter a tweet's display.
          list.append('
' + avatar + date + join + text + '
');

          list.children('li:first').addClass('tweet_first');
          list.children('li:odd').addClass('tweet_even');
          list.children('li:even').addClass('tweet_odd');
        });
        if (s.outro_text) list.after(outro);
        $(widget).trigger("loaded").trigger((tweets.length == 0 ? "empty" : "full"));
      });

    });
  };
})(jQuery);
<commit_msg>replaced relative time with code from http://github.com/elektronaut/jquery.livetwitter<commit_after>(function($) {

  $.fn.tweet = function(o){
    var s = {
      username: ["seaofclouds"],              // [string]   required, unless you want to display our tweets. :) it can be an array, just do ["username1","username2","etc"]
      list: null,                              //[string]   optional name of list belonging to username
      avatar_size: null,                      // [integer]  height and width of avatar if displayed (48px max)
      count: 3,                               // [integer]  how many tweets to display?
      intro_text: null,                       // [string]   do you want text BEFORE your your tweets?
      outro_text: null,                       // [string]   do you want text AFTER your tweets?
      join_text:  null,                       // [string]   optional text in between date and tweet, try setting to "auto"
      auto_join_text_default: "i said,",      // [string]   auto text for non verb: "i said" bullocks
      auto_join_text_ed: "i",                 // [string]   auto text for past tense: "i" surfed
      auto_join_text_ing: "i am",             // [string]   auto tense for present tense: "i was" surfing
      auto_join_text_reply: "i replied to",   // [string]   auto tense for replies: "i replied to" @someone "with"
      auto_join_text_url: "i was looking at", // [string]   auto tense for urls: "i was looking at" http:...
      loading_text: null,                     // [string]   optional loading text, displayed while tweets load
      query: null                             // [string]   optional search query
    };

    if(o) $.extend(s, o);

    $.fn.extend({
      linkUrl: function() {
        var returning = [];
        var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi;
        this.each(function() {
          returning.push(this.replace(regexp,"$1"));
        });
        return $(returning);
      },
      linkUser: function() {
        var returning = [];
        var regexp = /[\@]+([A-Za-z0-9-_]+)/gi;
        this.each(function() {
          returning.push(this.replace(regexp,"@$1"));
        });
        return $(returning);
      },
      linkHash: function() {
        var returning = [];
        var regexp = /(?:^| )[\#]+([A-Za-z0-9-_]+)/gi;
        this.each(function() {
          returning.push(this.replace(regexp, ' #$1'));
        });
        return $(returning);
      },
      capAwesome: function() {
        var returning = [];
        this.each(function() {
          returning.push(this.replace(/\b(awesome)\b/gi, '$1'));
        });
        return $(returning);
      },
      capEpic: function() {
        var returning = [];
        this.each(function() {
          returning.push(this.replace(/\b(epic)\b/gi, '$1'));
        });
        return $(returning);
      },
      makeHeart: function() {
        var returning = [];
        this.each(function() {
          returning.push(this.replace(/(<)+[3]/gi, "<tt class='heart'>♥</tt>"));
        });
        return $(returning);
      }
    });

    function parse_date(date_str) {
      // The non-search twitter APIs return inconsistently-formatted dates, which Date.parse
      // cannot handle in IE. We therefore perform the following transformation:
      // "Wed Apr 29 08:53:31 +0000 2009" => "Wed, Apr 29 2009 08:53:31 +0000"
      return Date.parse(date_str.replace(/^([a-z]{3})( [a-z]{3} \d\d?)(.*)( \d{4})$/i, '$1,$2$4$3'));
    }

    function relative_time(time_value) {
      var parsed_date = parse_date(time_value);
      var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
      var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
      var r = '';
      if (delta < 60) {
				r = delta + ' seconds ago';
			} else if(delta < 120) {
				r = 'a minute ago';
			} else if(delta < (45*60)) {
				r = (parseInt(delta / 60, 10)).toString() + ' minutes ago';
			} else if(delta < (90*60)) {
				r = 'an hour ago';
			} else if(delta < (24*60*60)) {
				r = '' + (parseInt(delta / 3600, 10)).toString() + ' hours ago';
			} else if(delta < (48*60*60)) {
				r = 'a day ago';
			} else {
				r = (parseInt(delta / 86400, 10)).toString() + ' days ago';
			}
				return r;
    }

    function build_url() {
      var proto = ('https:' == document.location.protocol ? 'https:' : 'http:');
      if (s.list) {
        return proto+"//api.twitter.com/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+s.count+"&callback=?";
      } else if (s.query == null && s.username.length == 1) {
        return proto+'//api.twitter.com/1/statuses/user_timeline.json?screen_name='+s.username[0]+'&count='+s.count+'&include_rts=1&callback=?';
      } else {
        var query = (s.query || 'from:'+s.username.join(' OR from:'));
        return proto+'//search.twitter.com/search.json?&q='+encodeURIComponent(query)+'&rpp='+s.count+'&callback=?';
      }
    }

    return this.each(function(i, widget){
      var list = $('
').appendTo(widget);
      var intro = '
'+s.intro_text+'
';
      var outro = '
'+s.outro_text+'
';
      var loading = $('
'+s.loading_text+'
');

      if(typeof(s.username) == "string"){
        s.username = [s.username];
      }

      if (s.loading_text) $(widget).append(loading);
      $.getJSON(build_url(), function(data){
        if (s.loading_text) loading.remove();
        if (s.intro_text) list.before(intro);
        var tweets = (data.results || data);
        $.each(tweets, function(i,item){
          // auto join text based on verb tense and content
          if (s.join_text == "auto") {
            if (item.text.match(/^(@([A-Za-z0-9-_]+)) .*/i)) {
              var join_text = s.auto_join_text_reply;
            } else if (item.text.match(/(^\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+) .*/i)) {
              var join_text = s.auto_join_text_url;
            } else if (item.text.match(/^((\w+ed)|just) .*/im)) {
              var join_text = s.auto_join_text_ed;
            } else if (item.text.match(/^(\w*ing) .*/i)) {
              var join_text = s.auto_join_text_ing;
            } else {
              var join_text = s.auto_join_text_default;
            }
          } else {
            var join_text = s.join_text;
          };

          var from_user = item.from_user || item.user.screen_name;
          var profile_image_url = item.profile_image_url || item.user.profile_image_url;
          var join_template = ' '+join_text+' ';
          var join = ((s.join_text) ? join_template : ' ');
          var avatar_template = '';
          var avatar = (s.avatar_size ? avatar_template : '');
          var date = ''+relative_time(item.created_at)+'';
          var text = '' +$([item.text]).linkUrl().linkUser().linkHash().makeHeart().capAwesome().capEpic()[0]+ '';

          // until we create a template option, arrange the items below to alter a tweet's display.
          list.append('
' + avatar + date + join + text + '
');

          list.children('li:first').addClass('tweet_first');
          list.children('li:odd').addClass('tweet_even');
          list.children('li:even').addClass('tweet_odd');
        });
        if (s.outro_text) list.after(outro);
        $(widget).trigger("loaded").trigger((tweets.length == 0 ? "empty" : "full"));
      });

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


<commit_before>#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

function getTree(directoryPath, set) {
  set = set || new Set();
  const tree = {};
  const packagePath = path.join(directoryPath, 'package.json');
  if (!fs.existsSync(packagePath)) {
    return tree;
  }
  const dependencies = require(packagePath).dependencies || {};
  for (let dependency in dependencies) {
    if (set.has(dependency)) {
      continue;
    }
    set.add(dependency);
    let relativePath;
    if (dependency.startsWith('@')) {
      let [scope, name] = dependency.split('/');
      relativePath = path.join(scope, name);
    } else {
      relativePath = dependency;
    }
    let subDirectoryPath = directoryPath;
    while (!tree[dependency]) {
      const absolutePath = path.join(subDirectoryPath, 'node_modules', relativePath);
      if (fs.existsSync(absolutePath)) {
        tree[dependency] = getTree(absolutePath, new Set(set));
      } else {
        if (subDirectoryPath === '/') {
          break;
        }
        subDirectoryPath = path.resolve(path.join(subDirectoryPath, '..'));
      }
    }
    tree[dependency] = tree[dependency] || {};
  }
  return tree;
}

function formatTree(tree, deepth = 0) {
  let formattedTree = '';
  for (const dependency in tree) {
    formattedTree += `${'  '.repeat(deepth)}- [${dependency}](https://www.npmjs.com/package/${dependency})\n`;
    formattedTree += formatTree(tree[dependency], deepth + 1);
  }
  return formattedTree;
}

function directCountTree(tree) {
  let count = 0;
  for (const dependency in tree) {
    count += 1;
  }
  return count;
}

function countTree(tree, set) {
  if (!set) {
    set = new Set();
  }
  for (const dependency in tree) {
    set.add(dependency);
    countTree(tree[dependency], set);
  }
  return set.size;
}

function formatCount(count) {
  const dimensions = {
    M: 1000000,
    k: 1000,
  };
  for (const suffix in dimensions) {
    const divisor = dimensions[suffix];
    if (count >= divisor) {
      count = parseInt(count / parseInt(divisor / 10));
      count = `${count / 10}${suffix}`;
      break;
    }
  }
  return count;
}

function getColor(count) {
  if (count === 0) {
    return 'green';
  }
  return 'blue';
}

function dependenciesBadge(directoryPath) {
  const tree = getTree(directoryPath);
  const directCount = directCountTree(tree);
  const formattedDirectCount = formatCount(directCount);
  const count = countTree(tree);
  const formattedCount = formatCount(count);

  fs.writeFileSync(
    path.join(directoryPath, 'DEPENDENCIES.md'),
    `# Dependencies\n\nDirectly: ${formattedDirectCount}\n\nIndirectly: ${formattedCount}\n${
      count ? `\n${formatTree(tree)}` : ''
      }`
  );

  let readme;
  try {
    readme = fs.readFileSync(path.join(directoryPath, 'README.md'));
  } catch (e) {}
  const dependencies = `[![dependencies | ${formattedDirectCount} | ${formattedCount}](https://img.shields.io/badge/dependencies-${formattedDirectCount}%20|%20${formattedCount}-${getColor(
    count
  )}.svg)](DEPENDENCIES.md)`;
  if (readme) {
    readme = readme.toString();
    const regex = /\[\!\[dependencies \| .*?\]\(https:\/\/img\.shields\.io\/badge\/dependencies-.*?-.*?\.svg\)\]\(DEPENDENCIES.md\)/;
    if (regex.test(readme)) {
      readme = readme.replace(regex, dependencies);
    } else {
      readme = `${dependencies}\n\n${readme}`;
    }
  } else {
    readme = `${dependencies}\n`;
  }
  fs.writeFileSync(path.join(directoryPath, 'README.md'), readme);
}

(async () => {
  dependenciesBadge(process.cwd());
  if (fs.existsSync(path.join(process.cwd(), 'lerna.json'))) {
    try {
      const packagesPath = path.join(process.cwd(), 'packages');
      const dirs = fs.readdirSync(packagesPath);
      for (const dir of dirs) {
        dependenciesBadge(path.join(packagesPath, dir));
      }
    } catch (e) {}
  }
})();
<commit_msg>Add the count of dependencies for every tree leaf<commit_after>#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

function getTree(directoryPath, set) {
  set = set || new Set();
  const tree = {};
  const packagePath = path.join(directoryPath, 'package.json');
  if (!fs.existsSync(packagePath)) {
    return tree;
  }
  const dependencies = require(packagePath).dependencies || {};
  for (let dependency in dependencies) {
    if (set.has(dependency)) {
      continue;
    }
    set.add(dependency);
    let relativePath;
    if (dependency.startsWith('@')) {
      let [scope, name] = dependency.split('/');
      relativePath = path.join(scope, name);
    } else {
      relativePath = dependency;
    }
    let subDirectoryPath = directoryPath;
    while (!tree[dependency]) {
      const absolutePath = path.join(subDirectoryPath, 'node_modules', relativePath);
      if (fs.existsSync(absolutePath)) {
        tree[dependency] = getTree(absolutePath, new Set(set));
      } else {
        if (subDirectoryPath === '/') {
          break;
        }
        subDirectoryPath = path.resolve(path.join(subDirectoryPath, '..'));
      }
    }
    tree[dependency] = tree[dependency] || {};
  }
  return tree;
}

function formatTree(tree, deepth = 0) {
  let formattedTree = '';
  for (const dependency in tree) {
    formattedTree += `${'  '.repeat(deepth)}`;
    const subCount = directCountTree(tree[dependency]);
    formattedTree += `- [${dependency}](https://www.npmjs.com/package/${dependency}) (${subCount})\n`;

    formattedTree += formatTree(tree[dependency], deepth + 1);
  }
  return formattedTree;
}

function directCountTree(tree) {
  let count = 0;
  for (const dependency in tree) {
    count += 1;
  }
  return count;
}

function countTree(tree, set) {
  if (!set) {
    set = new Set();
  }
  for (const dependency in tree) {
    set.add(dependency);
    countTree(tree[dependency], set);
  }
  return set.size;
}

function formatCount(count) {
  const dimensions = {
    M: 1000000,
    k: 1000,
  };
  for (const suffix in dimensions) {
    const divisor = dimensions[suffix];
    if (count >= divisor) {
      count = parseInt(count / parseInt(divisor / 10));
      count = `${count / 10}${suffix}`;
      break;
    }
  }
  return count;
}

function getColor(count) {
  if (count === 0) {
    return 'green';
  }
  return 'blue';
}

function dependenciesBadge(directoryPath) {
  const tree = getTree(directoryPath);
  const directCount = directCountTree(tree);
  const formattedDirectCount = formatCount(directCount);
  const count = countTree(tree);
  const formattedCount = formatCount(count);

  fs.writeFileSync(
    path.join(directoryPath, 'DEPENDENCIES.md'),
    `# Dependencies\n\nDirectly: ${formattedDirectCount}\n\nIndirectly: ${formattedCount}\n${
      count ? `\n${formatTree(tree)}` : ''
    }`
  );

  let readme;
  try {
    readme = fs.readFileSync(path.join(directoryPath, 'README.md'));
  } catch (e) {}
  const dependencies = `[![dependencies | ${formattedDirectCount} | ${formattedCount}](https://img.shields.io/badge/dependencies-${formattedDirectCount}%20|%20${formattedCount}-${getColor(
    count
  )}.svg)](DEPENDENCIES.md)`;
  if (readme) {
    readme = readme.toString();
    const regex = /\[\!\[dependencies \| .*?\]\(https:\/\/img\.shields\.io\/badge\/dependencies-.*?-.*?\.svg\)\]\(DEPENDENCIES.md\)/;
    if (regex.test(readme)) {
      readme = readme.replace(regex, dependencies);
    } else {
      readme = `${dependencies}\n\n${readme}`;
    }
  } else {
    readme = `${dependencies}\n`;
  }
  fs.writeFileSync(path.join(directoryPath, 'README.md'), readme);
}

(async () => {
  dependenciesBadge(process.cwd());
  if (fs.existsSync(path.join(process.cwd(), 'lerna.json'))) {
    try {
      const packagesPath = path.join(process.cwd(), 'packages');
      const dirs = fs.readdirSync(packagesPath);
      for (const dir of dirs) {
        dependenciesBadge(path.join(packagesPath, dir));
      }
    } catch (e) {}
  }
})();
<|endoftext|>


<commit_before>/**
 * Copyright (c) ActiveState 2013 - ALL RIGHTS RESERVED.
 */

if (typeof define !== 'function') { var define = require('amdefine')(module) }

define([typeof window === 'undefined' ? 'events' : 'event-emitter',
        './lib/collection',
        './lib/apps',
        './lib/spaces',
        './lib/space-quota-definitions',
        './lib/routes',
        './lib/events',
        './lib/app-usage-events',
        './lib/feature-flags',
        './lib/jobs',
        './lib/users',
        './lib/organizations',
        './lib/http-client'],
    function (EventEmitter, Collection, Apps, Spaces, SpaceQuotaDefinitions, Routes, Events, AppUsageEvents, FeatureFlags, Jobs, Users, Organizations, HttpClient) {

        /*
         Generic CF resources that follow the standard pattern with no unique functionality.
         For other resources that do have unique functionality or don't support the standard set of verbs then derive an
         object off of collection and add or remove specific functions.
         */
        var generic_collections = [
            'domains',
            'private_domains',
            'shared_domains',
            'quota_definitions',
            'service_bindings',
            'service_plans',
            'services',
            'service_instances',
            'user_provided_service_instances',
            'buildpacks'];

        var api = function (api_endpoint, options) {

            options = options || {};

            this.api_endpoint = api_endpoint;
            this.authorization_endpoint = options.authorization_endpoint || null;
            this.http_client = new HttpClient(options);
            this.token = options.token || null;
            this.scopes = options.scopes || null;
            this.redirect_uri = options.redirect_uri || null;
            this.client_id = options.client_id || 'cf';
            this.apps = new Apps(this);
            this.events = new Events(this);
            this.app_usage_events = new AppUsageEvents(this);
            this.feature_flags = new FeatureFlags(this);
            this.jobs = new Jobs(this);
            this.users = new Users(this);
            this.spaces = new Spaces(this);
            this.space_quota_definitions = new SpaceQuotaDefinitions(this);
            this.routes = new Routes(this);
            this.organizations = new Organizations(this);

            this.initializeGenericCollections();
            this.initialize();
        };

        if (typeof window === 'undefined') {
            api.prototype.__proto__ = EventEmitter.EventEmitter.prototype;
        } else {
            api.prototype = Object.create(new EventEmitter());
        }

        var makeErrorMessageFromResponse = function (res) {

            var response_body = res.body;
            if (typeof response_body !== 'string') {
                try {
                    response_body = JSON.stringify(response_body);
                } catch (e) {
                    /* eat it */
                }
            }

            return 'Status: ' + res.status_code + '. Response: ' + response_body;
        };

        var makeResponseError = function (err, res) {
            if (!err) {
                err = new Error(makeErrorMessageFromResponse(res));
            }
            err.status_code = res ? res.status_code : 0;
            return err;
        };

        api.prototype.initialize = function () {
            /* faux-constructor to use as an extension point for derived clients */
        };

        api.prototype.initializeGenericCollections = function () {

            var self = this;
            generic_collections.forEach(function (collection_name) {
                var collection = new Collection();
                collection.collection = collection_name;
                collection.api = self;
                self[collection_name] = collection;
            });
        };

        api.prototype.makeAuthorizationHeader = function () {
            return 'bearer ' + this.token;
        };

        api.prototype.addAuthorizationHeaderToOptions = function (options) {
            options.headers['Authorization'] = this.makeAuthorizationHeader();
        };

        api.prototype.normalizeOptions = function (options) {

            options = options || {};
            options.headers = options.headers || {};
            options.global = typeof options.global === 'undefined' ? true : options.global;

            if (this.token) {
                this.addAuthorizationHeaderToOptions(options);
            }

            return options;
        };

        api.prototype.getAuthorizationEndpoint = function (done) {

            var self = this;
            if (this.authorization_endpoint) {
                setTimeout(function () {
                    done(null, self.authorization_endpoint)
                }, 1);
            } else {
                this.get('/info', {status_code: 200}, function (err, res) {
                    if (err) {return done(err);}
                    self.authorization_endpoint = res.body.authorization_endpoint;
                    done(null, self.authorization_endpoint);
                });
            }
        };

        api.prototype.authorize = function () {
            if (typeof window !== 'undefined') {
                this.authorizeBrowser();
            } else {
                this.authorizeNodejs();
            }
        };

        api.prototype.authorizeBrowser = function () {

            if (this.authorizing) {return;}

            var self = this;
            this.token = null;
            this.authorizing = true;

            this.getAuthorizationEndpoint(function (err, authorization_endpoint) {

                var oauth_url = authorization_endpoint + '/oauth/authorize?' +
                    'response_type=token&' +
                    'client_id=' + encodeURIComponent(self.client_id) + '&' +
                    'redirect_uri=' + encodeURIComponent(self.redirect_uri);

                if (self.scopes) {
                    oauth_url = oauth_url + '&scope=' + encodeURIComponent(self.scopes);
                }

                window.location = oauth_url;
            });
        };

        api.prototype.authorizeNodejs = function (res, done) {

            /**
             * 1. If acting on behalf of a user e.g. just passing through a user token then a 401 is an error that should bubble out to the user
             * 2. If acting as a resource server a 401 should trigger a refresh token attempt and failing that it should try to re-authenticate using client credentials
             *
             * Assume 1. for now until 2. is implemented. Users of this lib could override this function to patch in their desired behaviour.
             */
            if (done) {
                done(new Error(makeErrorMessageFromResponse(res)), res);
            }
        };

        api.prototype.triggerGlobalError = function (err, options, res) {
            if (options.global) {
                this.emit('http_error', err, res, options);
            }
        };

        api.prototype.processResponse = function (options, err, res, done) {

            if (err) {
                err = makeResponseError(err, res);
                this.triggerGlobalError(err, options, res);
                return done(err, res);
            }

            if (res.status_code === 401 && !options.ignore_unauthorized && typeof window !== 'undefined') {return this.authorizeBrowser();}
            if (res.status_code === 401 && !options.ignore_unauthorized && typeof window === 'undefined') {return this.authorizeNodejs(res, done);}

            if ((options.status_code && options.status_code !== res.status_code) ||
                (options.status_codes && options.status_codes.indexOf(res.status_code) === -1)) {
                var error = makeResponseError(null, res);
                this.triggerGlobalError(error, options, res);
                return done(error, res);
            }

            this.marshalResponse(options, res, done);
        };

        api.prototype.marshalResponse = function (options, res, done) {
            /* this is effectively a no-op implementation. derived clients can use it to modify the response. */
            var self = this;
            setTimeout(function () {
                done.call(self, null, res);
            }, 1);
        };

        api.prototype.marshalRequest = function (url, options, done) {
            /* this is effectively a no-op implementation. derived clients can use it to modify the request. */
            var self = this;
            setTimeout(function () {
                done.call(self, null, url, options);
            }, 1);
        };

        api.prototype.executeRequest = function (path, options, done) {

            // Allow the special case where api components may need to talk to the UAA with it's own host.
            var prepend_host = true;
            if (path.indexOf('http') !== -1) {
                prepend_host = false;
            }

            var self = this;
            this.marshalRequest(path, options, function (err, path, options) {
                if (err) {return done(err);}

                self.http_client.request(
                        (prepend_host ? self.api_endpoint : '') + path + (options.query ? options.query : ''),
                    options,
                    function (err, res) {
                        self.processResponse(options, err, res, done);
                    }
                );
            });
        };

        api.prototype.getApiInfo = function (options, done) {

            if (typeof options === 'function' && typeof done === 'undefined') {
                done = options;
                options = null;
            }

            options = options || {};
            options.status_code = 200;

            this.get('/v2/info', options, function (err, res) {
                done(err, res ? res.body : null);
            });
        };

        api.prototype.get = function (path, options, done) {

            options = this.normalizeOptions(options);
            options.verb = 'GET';
            options.path = path;

            if (!options.status_code && !options.status_codes) {
                options.status_code = 200;
            }

            this.executeRequest(path, options, done);
        };

        api.prototype.delete_ = function (path, options, done) {

            options = this.normalizeOptions(options);
            options.verb = 'DELETE';
            options.path = path;

            if (!options.status_code && !options.status_codes) {
                options.status_code = 200;
            }

            this.executeRequest(path, options, done);
        };

        api.prototype.put = function (path, options, done) {

            options = this.normalizeOptions(options);
            options.verb = 'PUT';
            options.path = path;

            if (!options.status_code && !options.status_codes) {
                options.status_code = 200;
            }

            this.executeRequest(path, options, done);
        };

        api.prototype.post = function (path, options, done) {

            options = this.normalizeOptions(options);
            options.verb = 'POST';
            options.path = path;

            if (!options.status_code && !options.status_codes) {
                options.status_code = 201;
            }

            this.executeRequest(path, options, done);
        };

        return api;
    }
);
<commit_msg>300063 - support authorization grant OAuth2 flow for browser clients.<commit_after>/**
 * Copyright (c) ActiveState 2013 - ALL RIGHTS RESERVED.
 */

if (typeof define !== 'function') { var define = require('amdefine')(module) }

define([typeof window === 'undefined' ? 'events' : 'event-emitter',
        './lib/collection',
        './lib/apps',
        './lib/spaces',
        './lib/space-quota-definitions',
        './lib/routes',
        './lib/events',
        './lib/app-usage-events',
        './lib/feature-flags',
        './lib/jobs',
        './lib/users',
        './lib/organizations',
        './lib/http-client'],
    function (EventEmitter, Collection, Apps, Spaces, SpaceQuotaDefinitions, Routes, Events, AppUsageEvents, FeatureFlags, Jobs, Users, Organizations, HttpClient) {

        /*
         Generic CF resources that follow the standard pattern with no unique functionality.
         For other resources that do have unique functionality or don't support the standard set of verbs then derive an
         object off of collection and add or remove specific functions.
         */
        var generic_collections = [
            'domains',
            'private_domains',
            'shared_domains',
            'quota_definitions',
            'service_bindings',
            'service_plans',
            'services',
            'service_instances',
            'user_provided_service_instances',
            'buildpacks'];

        var api = function (api_endpoint, options) {

            options = options || {};

            this.api_endpoint = api_endpoint;
            this.authorization_endpoint = options.authorization_endpoint || null;
            this.http_client = new HttpClient(options);
            this.token = options.token || null;
            this.scopes = options.scopes || null;
            this.redirect_uri = options.redirect_uri || null;
            this.client_id = options.client_id || 'cf';
            this.response_type = options.response_type || 'token';
            this.apps = new Apps(this);
            this.events = new Events(this);
            this.app_usage_events = new AppUsageEvents(this);
            this.feature_flags = new FeatureFlags(this);
            this.jobs = new Jobs(this);
            this.users = new Users(this);
            this.spaces = new Spaces(this);
            this.space_quota_definitions = new SpaceQuotaDefinitions(this);
            this.routes = new Routes(this);
            this.organizations = new Organizations(this);

            this.initializeGenericCollections();
            this.initialize();
        };

        if (typeof window === 'undefined') {
            api.prototype.__proto__ = EventEmitter.EventEmitter.prototype;
        } else {
            api.prototype = Object.create(new EventEmitter());
        }

        var makeErrorMessageFromResponse = function (res) {

            var response_body = res.body;
            if (typeof response_body !== 'string') {
                try {
                    response_body = JSON.stringify(response_body);
                } catch (e) {
                    /* eat it */
                }
            }

            return 'Status: ' + res.status_code + '. Response: ' + response_body;
        };

        var makeResponseError = function (err, res) {
            if (!err) {
                err = new Error(makeErrorMessageFromResponse(res));
            }
            err.status_code = res ? res.status_code : 0;
            return err;
        };

        api.prototype.initialize = function () {
            /* faux-constructor to use as an extension point for derived clients */
        };

        api.prototype.initializeGenericCollections = function () {

            var self = this;
            generic_collections.forEach(function (collection_name) {
                var collection = new Collection();
                collection.collection = collection_name;
                collection.api = self;
                self[collection_name] = collection;
            });
        };

        api.prototype.makeAuthorizationHeader = function () {
            return 'bearer ' + this.token;
        };

        api.prototype.addAuthorizationHeaderToOptions = function (options) {
            options.headers['Authorization'] = this.makeAuthorizationHeader();
        };

        api.prototype.normalizeOptions = function (options) {

            options = options || {};
            options.headers = options.headers || {};
            options.global = typeof options.global === 'undefined' ? true : options.global;

            if (this.token) {
                this.addAuthorizationHeaderToOptions(options);
            }

            return options;
        };

        api.prototype.getAuthorizationEndpoint = function (done) {

            var self = this;
            if (this.authorization_endpoint) {
                setTimeout(function () {
                    done(null, self.authorization_endpoint)
                }, 1);
            } else {
                this.get('/info', {status_code: 200}, function (err, res) {
                    if (err) {return done(err);}
                    self.authorization_endpoint = res.body.authorization_endpoint;
                    done(null, self.authorization_endpoint);
                });
            }
        };

        api.prototype.authorize = function () {
            if (typeof window !== 'undefined') {
                this.authorizeBrowser();
            } else {
                this.authorizeNodejs();
            }
        };

        api.prototype.authorizeBrowser = function () {

            if (this.authorizing) {return;}

            var self = this;
            this.token = null;
            this.authorizing = true;

            // If response_type is 'code' then assume redirect_uri points to a backend that will handle the authorization
            // grant OAuth2 flow on behalf of the browser client. Typically used to avoid exposing the OAuth2 token to
            // the browser (e.g. backend will issue a session cookie etc. instead of raw token).
            if (this.response_type === 'code') {
                window.location = this.redirect_uri;
            } else {
                this.getAuthorizationEndpoint(function (err, authorization_endpoint) {

                    var oauth_url = authorization_endpoint + '/oauth/authorize?' +
                        'response_type=' + encodeURIComponent(self.response_type) + '&' +
                        'client_id=' + encodeURIComponent(self.client_id) + '&' +
                        'redirect_uri=' + encodeURIComponent(self.redirect_uri);

                    if (self.scopes) {
                        oauth_url = oauth_url + '&scope=' + encodeURIComponent(self.scopes);
                    }

                    window.location = oauth_url;
                });
            }
        };

        api.prototype.authorizeNodejs = function (res, done) {

            /**
             * 1. If acting on behalf of a user e.g. just passing through a user token then a 401 is an error that should bubble out to the user
             * 2. If acting as a resource server a 401 should trigger a refresh token attempt and failing that it should try to re-authenticate using client credentials
             *
             * Assume 1. for now until 2. is implemented. Users of this lib could override this function to patch in their desired behaviour.
             */
            if (done) {
                done(new Error(makeErrorMessageFromResponse(res)), res);
            }
        };

        api.prototype.triggerGlobalError = function (err, options, res) {
            if (options.global) {
                this.emit('http_error', err, res, options);
            }
        };

        api.prototype.processResponse = function (options, err, res, done) {

            if (err) {
                err = makeResponseError(err, res);
                this.triggerGlobalError(err, options, res);
                return done(err, res);
            }

            if (res.status_code === 401 && !options.ignore_unauthorized && typeof window !== 'undefined') {return this.authorizeBrowser();}
            if (res.status_code === 401 && !options.ignore_unauthorized && typeof window === 'undefined') {return this.authorizeNodejs(res, done);}

            if ((options.status_code && options.status_code !== res.status_code) ||
                (options.status_codes && options.status_codes.indexOf(res.status_code) === -1)) {
                var error = makeResponseError(null, res);
                this.triggerGlobalError(error, options, res);
                return done(error, res);
            }

            this.marshalResponse(options, res, done);
        };

        api.prototype.marshalResponse = function (options, res, done) {
            /* this is effectively a no-op implementation. derived clients can use it to modify the response. */
            var self = this;
            setTimeout(function () {
                done.call(self, null, res);
            }, 1);
        };

        api.prototype.marshalRequest = function (url, options, done) {
            /* this is effectively a no-op implementation. derived clients can use it to modify the request. */
            var self = this;
            setTimeout(function () {
                done.call(self, null, url, options);
            }, 1);
        };

        api.prototype.executeRequest = function (path, options, done) {

            // Allow the special case where api components may need to talk to the UAA with it's own host.
            var prepend_host = true;
            if (path.indexOf('http') !== -1) {
                prepend_host = false;
            }

            var self = this;
            this.marshalRequest(path, options, function (err, path, options) {
                if (err) {return done(err);}

                self.http_client.request(
                    (prepend_host ? self.api_endpoint : '') + path + (options.query ? options.query : ''),
                    options,
                    function (err, res) {
                        self.processResponse(options, err, res, done);
                    }
                );
            });
        };

        api.prototype.getApiInfo = function (options, done) {

            if (typeof options === 'function' && typeof done === 'undefined') {
                done = options;
                options = null;
            }

            options = options || {};
            options.status_code = 200;

            this.get('/v2/info', options, function (err, res) {
                done(err, res ? res.body : null);
            });
        };

        api.prototype.get = function (path, options, done) {

            options = this.normalizeOptions(options);
            options.verb = 'GET';
            options.path = path;

            if (!options.status_code && !options.status_codes) {
                options.status_code = 200;
            }

            this.executeRequest(path, options, done);
        };

        api.prototype.delete_ = function (path, options, done) {

            options = this.normalizeOptions(options);
            options.verb = 'DELETE';
            options.path = path;

            if (!options.status_code && !options.status_codes) {
                options.status_code = 200;
            }

            this.executeRequest(path, options, done);
        };

        api.prototype.put = function (path, options, done) {

            options = this.normalizeOptions(options);
            options.verb = 'PUT';
            options.path = path;

            if (!options.status_code && !options.status_codes) {
                options.status_code = 200;
            }

            this.executeRequest(path, options, done);
        };

        api.prototype.post = function (path, options, done) {

            options = this.normalizeOptions(options);
            options.verb = 'POST';
            options.path = path;

            if (!options.status_code && !options.status_codes) {
                options.status_code = 201;
            }

            this.executeRequest(path, options, done);
        };

        return api;
    }
);
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 Conjur Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

module.exports = {
  u: require('underscore'),
  assert: require('assert'),
  util: require('util'),
  async: require('async'),
  rest: require('restler'),
  https: require('https'),
  format: require('util').format,
  inspect: require('util').inspect,
  escape: encodeURIComponent,
  info: require('winston').info,
  pathEscape: function(str) {
    return encodeURIComponent(str);
  },
  username: function(token) {
    if ( typeof(token['data']) !== "string" ) {
      require('winston').warn("Expecting string in token[data]");
    }
    return token['data'];
  },
  currentRole: function(account, token) {
    var match;
    var username = module.exports.username(token);
    if ( match = username.match(/([^/]*)\/(.*)/) )
      return [ account, match[1], match[2] ].join(':');
    else
      return [ account, 'user', username ].join(':');
  },
  authorizationHeader: function(token) {
    return { headers: { 'Authorization': require('./conjur/authn').tokenHeader(token) } };
  },
  getURL: function(url, options, callback) {
    if ( !callback ) {
      callback = options;
      options = {};
    }
    require('winston').info(url);
    require('restler').get(url, options).on('complete', function(result, response) {
      if ( result instanceof Error ) return callback(result);
      if ( response.statusCode !== 200 ) return callback({code: response.statusCode, message: require('util').format("HTTP status code %s fetching %s", response.statusCode, require('util').inspect(url))});

      callback(null, result);
    });
  }
}
<commit_msg>add a helper function<commit_after>/*
 * Copyright (C) 2013 Conjur Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

module.exports = {
  u: require('underscore'),
  assert: require('assert'),
  util: require('util'),
  async: require('async'),
  rest: require('restler'),
  https: require('https'),
  format: require('util').format,
  inspect: require('util').inspect,
  escape: encodeURIComponent,
  info: require('winston').info,
  pathEscape: function(str) {
    return encodeURIComponent(str);
  },
  username: function(token) {
    if ( typeof(token['data']) !== "string" ) {
      require('winston').warn("Expecting string in token[data]");
    }
    return token['data'];
  },
  currentRole: function(account, token) {
    var match;
    var username = module.exports.username(token);
    if ( match = username.match(/([^/]*)\/(.*)/) )
      return [ account, match[1], match[2] ].join(':');
    else
      return [ account, 'user', username ].join(':');
  },
  authorizationHeader: function(token) {
    return { headers: { 'Authorization': require('./conjur/authn').tokenHeader(token) } };
  },
  getURL: function(url, options, callback) {
    if ( !callback ) {
      callback = options;
      options = {};
    }
    require('winston').info(url);
    require('restler').get(url, options).on('complete', function(result, response) {
      if ( result instanceof Error ) return callback(result);
      if ( response.statusCode !== 200 ) return callback({code: response.statusCode, message: require('util').format("HTTP status code %s fetching %s", response.statusCode, require('util').inspect(url))});

      callback(null, result);
    });
  },
  arrayParam: function(name, array){
    var parts = []
    array.forEach(function(value){
      parts.push(module.exports.pathEscape(name + "[]=" + value));
    });
    return parts.join('&');
  }
}
<|endoftext|>


<commit_before>import api from '../consts'
import axios from 'axios'
import { addNotification } from './notificationActions'

const FETCH_USER_ACCOUNT_REQUESTED = 'FETCH_USER_ACCOUNT_REQUESTED'
const FETCH_USER_ACCOUNT_SUCCESS = 'FETCH_USER_ACCOUNT_SUCCESS'
const FETCH_USER_ACCOUNT_ERROR = 'FETCH_USER_ACCOUNT_ERROR'

const CREATE_USER_ACCOUNT_REQUESTED = 'CREATE_USER_ACCOUNT'
const CREATE_USER_ACCOUNT_SUCCESS = 'CREATE_USER_ACCOUNT_SUCCESS'
const CREATE_USER_ACCOUNT_ERROR = 'CREATE_USER_ACCOUNT_ERROR'

const UPDATE_USER_ACCOUNT_REQUESTED = 'UPDATE_USER_ACCOUNT_REQUESTED'
const UPDATE_USER_ACCOUNT_SUCCESS = 'UPDATE_USER_ACCOUNT_SUCCESS'
const UPDATE_USER_ACCOUNT_ERROR = 'UPDATE_USER_ACCOUNT_ERROR'

const CREATE_BANKACCOUNT_REQUESTED = 'CREATE_BANKACCOUNT_REQUESTED'
const CREATE_BANKACCOUNT_SUCCESS = 'CREATE_BANKACCOUNT_SUCCESS'
const CREATE_BANKACCOUNT_ERROR = 'CREATE_BANKACCOUNT_ERROR'

const GET_BANKACCOUNT_REQUESTED = 'GET_BANKACCOUNT_REQUESTED'
const GET_BANKACCOUNT_SUCCESS = 'GET_BANKACCOUNT_SUCCESS'
const GET_BANKACCOUNT_ERROR = 'GET_BANKACCOUNT_ERROR'

/*
 * Account fetch
 */

const fetchUserAccountRequested = () => {
  return { type: FETCH_USER_ACCOUNT_REQUESTED, completed: false }
}

const fetchUserAccountSuccess = account => {
  return {
    type: FETCH_USER_ACCOUNT_SUCCESS,
    completed: true,
    data: account.data
  }
}

const fetchUserAccountError = error => {
  return { type: FETCH_USER_ACCOUNT_ERROR, completed: true, error: error }
}

/*
 * Account create
 */

const createUserAccountRequested = () => {
  return { type: CREATE_USER_ACCOUNT_REQUESTED, completed: false }
}

const createUserAccountSuccess = account => {
  return {
    type: CREATE_USER_ACCOUNT_SUCCESS,
    completed: true,
    data: account.data
  }
}

const createUserAccountError = error => {
  return { type: CREATE_USER_ACCOUNT_ERROR, completed: true, error: error }
}

/*
 * Account update
 */

const updateUserAccountRequested = () => {
  return { type: UPDATE_USER_ACCOUNT_REQUESTED, completed: false }
}

const updateUserAccountSuccess = account => {
  return {
    type: UPDATE_USER_ACCOUNT_SUCCESS,
    completed: true,
    data: account.data
  }
}

const updateUserAccountError = error => {
  return { type: UPDATE_USER_ACCOUNT_ERROR, completed: true, error: error }
}

/*
 * Account bank get
 */

const getBankAccountRequested = () => {
  return { type: GET_BANKACCOUNT_REQUESTED, completed: false }
}

const getBankAccountSuccess = account => {
  return { type: GET_BANKACCOUNT_SUCCESS, completed: true, data: account.data }
}

const getBankAccountError = error => {
  return { type: GET_BANKACCOUNT_ERROR, completed: true, error: error }
}

/*
 * Account bank create
 */

const createBankAccountRequested = () => {
  return { type: CREATE_BANKACCOUNT_REQUESTED, completed: false }
}

const createBankAccountSuccess = account => {
  return {
    type: CREATE_BANKACCOUNT_SUCCESS,
    completed: true,
    data: account.data
  }
}

const createBankAccountError = error => {
  return { type: CREATE_BANKACCOUNT_ERROR, completed: true, error: error }
}

const fetchAccount = userId => {
  return (dispatch, getState) => {
    dispatch(fetchUserAccountRequested())
    return axios
      .get(api.API_URL + `/users/${userId}/account`)
      .then(account => {
        return dispatch(fetchUserAccountSuccess(account))
      })
      .catch(e => {
        // eslint-disable-next-line no-console
        console.log('fetch user account error', e)
        return dispatch(fetchUserAccountError(e))
      })
  }
}

const createAccount = userId => {
  return (dispatch, getState) => {
    dispatch(createUserAccountRequested())
    const accountId = getState().loggedIn.user.account_id
    if (accountId) {
      dispatch(addNotification('Já existe uma conta associada'))
      return dispatch(
        createUserAccountError({ message: 'Já existe uma conta associada' })
      )
    }
    axios
      .post(api.API_URL + '/user/account', {
        id: userId
      })
      .then(account => {
        dispatch(addNotification('Conta criada com sucesso'))
        return dispatch(createUserAccountSuccess(account))
      })
      .catch(error => {
        dispatch(addNotification('Erro ao tentar criar uma conta'))
        // eslint-disable-next-line no-console
        console.log('error on create account', error)
        return dispatch(createUserAccountError(error))
      })
  }
}

const updateAccount = (userId, accountData) => {
  return (dispatch, getState) => {
    dispatch(updateUserAccountRequested())
    axios
      .put(api.API_URL + '/user/account', {
        id: userId,
        account: accountData
      })
      .then(account => {
        dispatch(addNotification('Conta atualizada com sucesso'))
        // dispatch(fetchAccount());
        return dispatch(updateUserAccountSuccess(account))
      })
      .catch(error => {
        dispatch(
          addNotification(
            'Erro ao tentar atualizar sua conta. Você preencheu todos os dados?'
          )
        )
        // eslint-disable-next-line no-console
        console.log('error on create account', error)
        return dispatch(updateUserAccountError(error))
      })
  }
}

const getBankAccount = userId => {
  return (dispatch, getState) => {
    dispatch(getBankAccountRequested())
    axios
      .get(`${api.API_URL}/users/${userId}/bank_accounts`)
      .then(bankAccount => {
        if (bankAccount.data.statusCode === 400) {
          dispatch(addNotification('Erro ao tentar obter sua conta bancária'))
          return dispatch(getBankAccountError(bankAccount.data))
        }
        return dispatch(getBankAccountSuccess(bankAccount))
      })
      .catch(error => {
        dispatch(addNotification('Erro ao tentar atualizar sua conta'))
        // eslint-disable-next-line no-console
        console.log('error on create account', error)
        return dispatch(getBankAccountError(error))
      })
  }
}

const createBankAccount = (userId, bank) => {
  return (dispatch, getState) => {
    dispatch(createBankAccountRequested())
    axios
      .post(api.API_URL + '/user/bank_accounts', {
        id: userId,
        routing_number: bank.routing_number,
        account_number: bank.account_number
      })
      .then(bankAccount => {
        if (bankAccount.data.statusCode === 400) {
          dispatch(addNotification('Erro ao tentar atualizar sua conta'))
          return dispatch(createBankAccountError(bankAccount.data))
        }
        dispatch(addNotification('Conta bancária cadastrada com sucesso'))

        return dispatch(createBankAccountSuccess(bankAccount))
      })
      .catch(error => {
        dispatch(addNotification('Erro ao tentar atualizar sua conta'))
        // eslint-disable-next-line no-console
        console.log('error on create account', error)
        return dispatch(createBankAccountError(error))
      })
  }
}

export {
  FETCH_USER_ACCOUNT_REQUESTED,
  FETCH_USER_ACCOUNT_SUCCESS,
  FETCH_USER_ACCOUNT_ERROR,
  CREATE_USER_ACCOUNT_REQUESTED,
  CREATE_USER_ACCOUNT_SUCCESS,
  CREATE_USER_ACCOUNT_ERROR,
  UPDATE_USER_ACCOUNT_REQUESTED,
  UPDATE_USER_ACCOUNT_SUCCESS,
  UPDATE_USER_ACCOUNT_ERROR,
  GET_BANKACCOUNT_REQUESTED,
  GET_BANKACCOUNT_SUCCESS,
  GET_BANKACCOUNT_ERROR,
  CREATE_BANKACCOUNT_REQUESTED,
  CREATE_BANKACCOUNT_SUCCESS,
  CREATE_BANKACCOUNT_ERROR,
  fetchAccount,
  createAccount,
  updateAccount,
  createBankAccount,
  getBankAccount
}
<commit_msg>Changing validation message (#98)<commit_after>import api from '../consts'
import axios from 'axios'
import { addNotification } from './notificationActions'

const FETCH_USER_ACCOUNT_REQUESTED = 'FETCH_USER_ACCOUNT_REQUESTED'
const FETCH_USER_ACCOUNT_SUCCESS = 'FETCH_USER_ACCOUNT_SUCCESS'
const FETCH_USER_ACCOUNT_ERROR = 'FETCH_USER_ACCOUNT_ERROR'

const CREATE_USER_ACCOUNT_REQUESTED = 'CREATE_USER_ACCOUNT'
const CREATE_USER_ACCOUNT_SUCCESS = 'CREATE_USER_ACCOUNT_SUCCESS'
const CREATE_USER_ACCOUNT_ERROR = 'CREATE_USER_ACCOUNT_ERROR'

const UPDATE_USER_ACCOUNT_REQUESTED = 'UPDATE_USER_ACCOUNT_REQUESTED'
const UPDATE_USER_ACCOUNT_SUCCESS = 'UPDATE_USER_ACCOUNT_SUCCESS'
const UPDATE_USER_ACCOUNT_ERROR = 'UPDATE_USER_ACCOUNT_ERROR'

const CREATE_BANKACCOUNT_REQUESTED = 'CREATE_BANKACCOUNT_REQUESTED'
const CREATE_BANKACCOUNT_SUCCESS = 'CREATE_BANKACCOUNT_SUCCESS'
const CREATE_BANKACCOUNT_ERROR = 'CREATE_BANKACCOUNT_ERROR'

const GET_BANKACCOUNT_REQUESTED = 'GET_BANKACCOUNT_REQUESTED'
const GET_BANKACCOUNT_SUCCESS = 'GET_BANKACCOUNT_SUCCESS'
const GET_BANKACCOUNT_ERROR = 'GET_BANKACCOUNT_ERROR'

/*
 * Account fetch
 */

const fetchUserAccountRequested = () => {
  return { type: FETCH_USER_ACCOUNT_REQUESTED, completed: false }
}

const fetchUserAccountSuccess = account => {
  return {
    type: FETCH_USER_ACCOUNT_SUCCESS,
    completed: true,
    data: account.data
  }
}

const fetchUserAccountError = error => {
  return { type: FETCH_USER_ACCOUNT_ERROR, completed: true, error: error }
}

/*
 * Account create
 */

const createUserAccountRequested = () => {
  return { type: CREATE_USER_ACCOUNT_REQUESTED, completed: false }
}

const createUserAccountSuccess = account => {
  return {
    type: CREATE_USER_ACCOUNT_SUCCESS,
    completed: true,
    data: account.data
  }
}

const createUserAccountError = error => {
  return { type: CREATE_USER_ACCOUNT_ERROR, completed: true, error: error }
}

/*
 * Account update
 */

const updateUserAccountRequested = () => {
  return { type: UPDATE_USER_ACCOUNT_REQUESTED, completed: false }
}

const updateUserAccountSuccess = account => {
  return {
    type: UPDATE_USER_ACCOUNT_SUCCESS,
    completed: true,
    data: account.data
  }
}

const updateUserAccountError = error => {
  return { type: UPDATE_USER_ACCOUNT_ERROR, completed: true, error: error }
}

/*
 * Account bank get
 */

const getBankAccountRequested = () => {
  return { type: GET_BANKACCOUNT_REQUESTED, completed: false }
}

const getBankAccountSuccess = account => {
  return { type: GET_BANKACCOUNT_SUCCESS, completed: true, data: account.data }
}

const getBankAccountError = error => {
  return { type: GET_BANKACCOUNT_ERROR, completed: true, error: error }
}

/*
 * Account bank create
 */

const createBankAccountRequested = () => {
  return { type: CREATE_BANKACCOUNT_REQUESTED, completed: false }
}

const createBankAccountSuccess = account => {
  return {
    type: CREATE_BANKACCOUNT_SUCCESS,
    completed: true,
    data: account.data
  }
}

const createBankAccountError = error => {
  return { type: CREATE_BANKACCOUNT_ERROR, completed: true, error: error }
}

const fetchAccount = userId => {
  return (dispatch, getState) => {
    dispatch(fetchUserAccountRequested())
    return axios
      .get(api.API_URL + `/users/${userId}/account`)
      .then(account => {
        return dispatch(fetchUserAccountSuccess(account))
      })
      .catch(e => {
        // eslint-disable-next-line no-console
        console.log('fetch user account error', e)
        return dispatch(fetchUserAccountError(e))
      })
  }
}

const createAccount = userId => {
  return (dispatch, getState) => {
    dispatch(createUserAccountRequested())
    const accountId = getState().loggedIn.user.account_id
    if (accountId) {
      dispatch(addNotification('Já existe uma conta associada'))
      return dispatch(
        createUserAccountError({ message: 'Já existe uma conta associada' })
      )
    }
    axios
      .post(api.API_URL + '/user/account', {
        id: userId
      })
      .then(account => {
        dispatch(addNotification('Conta criada com sucesso'))
        return dispatch(createUserAccountSuccess(account))
      })
      .catch(error => {
        dispatch(addNotification('Não foi possível criar a conta, por favor tente novamente mais tarde.'))
        // eslint-disable-next-line no-console
        console.log('error on create account', error)
        return dispatch(createUserAccountError(error))
      })
  }
}

const updateAccount = (userId, accountData) => {
  return (dispatch, getState) => {
    dispatch(updateUserAccountRequested())
    axios
      .put(api.API_URL + '/user/account', {
        id: userId,
        account: accountData
      })
      .then(account => {
        dispatch(addNotification('Conta atualizada com sucesso'))
        // dispatch(fetchAccount());
        return dispatch(updateUserAccountSuccess(account))
      })
      .catch(error => {
        dispatch(
          addNotification(
            'Não foi possível atualizar sua conta. Você preencheu todos os dados?'
          )
        )
        // eslint-disable-next-line no-console
        console.log('error on create account', error)
        return dispatch(updateUserAccountError(error))
      })
  }
}

const getBankAccount = userId => {
  return (dispatch, getState) => {
    dispatch(getBankAccountRequested())
    axios
      .get(`${api.API_URL}/users/${userId}/bank_accounts`)
      .then(bankAccount => {
        if (bankAccount.data.statusCode === 400) {
          dispatch(addNotification('Não foi possível obter sua conta bancária'))
          return dispatch(getBankAccountError(bankAccount.data))
        }
        return dispatch(getBankAccountSuccess(bankAccount))
      })
      .catch(error => {
        dispatch(addNotification('Não foi possível atualizar sua conta'))
        // eslint-disable-next-line no-console
        console.log('error on create account', error)
        return dispatch(getBankAccountError(error))
      })
  }
}

const createBankAccount = (userId, bank) => {
  return (dispatch, getState) => {
    dispatch(createBankAccountRequested())
    axios
      .post(api.API_URL + '/user/bank_accounts', {
        id: userId,
        routing_number: bank.routing_number,
        account_number: bank.account_number
      })
      .then(bankAccount => {
        if (bankAccount.data.statusCode === 400) {
          dispatch(addNotification('Não foi possível atualizar sua conta'))
          return dispatch(createBankAccountError(bankAccount.data))
        }
        dispatch(addNotification('Conta bancária cadastrada com sucesso'))

        return dispatch(createBankAccountSuccess(bankAccount))
      })
      .catch(error => {
        dispatch(addNotification('Não foi possível atualizar sua conta'))
        // eslint-disable-next-line no-console
        console.log('error on create account', error)
        return dispatch(createBankAccountError(error))
      })
  }
}

export {
  FETCH_USER_ACCOUNT_REQUESTED,
  FETCH_USER_ACCOUNT_SUCCESS,
  FETCH_USER_ACCOUNT_ERROR,
  CREATE_USER_ACCOUNT_REQUESTED,
  CREATE_USER_ACCOUNT_SUCCESS,
  CREATE_USER_ACCOUNT_ERROR,
  UPDATE_USER_ACCOUNT_REQUESTED,
  UPDATE_USER_ACCOUNT_SUCCESS,
  UPDATE_USER_ACCOUNT_ERROR,
  GET_BANKACCOUNT_REQUESTED,
  GET_BANKACCOUNT_SUCCESS,
  GET_BANKACCOUNT_ERROR,
  CREATE_BANKACCOUNT_REQUESTED,
  CREATE_BANKACCOUNT_SUCCESS,
  CREATE_BANKACCOUNT_ERROR,
  fetchAccount,
  createAccount,
  updateAccount,
  createBankAccount,
  getBankAccount
}
<|endoftext|>


<commit_before>'use strict'
require('./style.less')

var Element = require('element')
Element.prototype.inject(
  require('element/lib/property/text'),
  require('element/lib/property/transform'),
  require('element/lib/events/drag')
)
var Observable = require('vjs/lib/observable')
var Hub = require('../../lib')
var uikit = require('uikit')
var uuid = require('vjs/lib/util/uuid').val

var hub = global.hub = new Hub({
  adapter: {
    inject: require('../../lib/adapter/websocket'),
    on: {
      connection () {
        connected.val = true
        console.log('CONNECTION')
      },
      close () {
        connected.val = false
        console.log('close')
      },
      error (err) {
        console.error('err!', err.stack)
      }
    }
  },
  text: {
    on: {
      data (data) {
        msgCount.val++
      }
    }
  }
})

var start = Date.now()
var now = new Observable(0)
var connected = new Observable(false)
var msgCount = new Observable({
  val: 0,
  lastSecond: 0
})

setInterval(() => {
  now.val++
  msgCount.lastSecond.val = msgCount.val
}, 1000)

var FireButton = new uikit.Button({
  properties: {
    updating: function(val) {
      this._updating = val
      this.set({
        text: val,
        css: val
      })
    }
  },
  text: {
    inject: require('vjs/lib/operator/transform'),
    $transform: (val) => val === true ? 'Stop updates' : 'Fire updates'
  },
  css: {
    inject: require('vjs/lib/operator/transform'),
    $transform: (val) => val === true ? 'ui-button active' : 'ui-button inactive'
  },
  on: {
    click () {
      this._updating.val = !this._updating.val
    }
  }
}).Constructor

var app = global.app = new Element({
  node: document.body,
  rendered: true,
  css: 'app',
  holder: {
    labels: {
      ChildConstructor: uikit.Badge,
      uuid: {
        message: { text: uuid }
      },
      time: {
        message: {
          text: {
            val: now,
            inject: require('uikit/lib/transform/time')
          }
        }
      },
      upstream: new uikit.InputBadge({
        message: { text: hub.adapter }
      }),
      instance: new uikit.InputBadge({
        message: { text: hub.adapter.instance }
      }),
      clock: new uikit.Label({
        text: {
          val: start,
          inject: require('uikit/lib/transform/time')
        }
      })
    },
    msgcnt: new uikit.Stat({
      title: { text: 'Messages' },
      counter: {
        text: {
          inject: require('uikit/lib/transform/number'),
          val: msgCount
        }
      }
    }),
    msg: new uikit.Stat({
      title: { text: 'Msg/s' },
      counter: {
        text: {
          inject: require('vjs/lib/operator/transform'),
          val: now,
          $transform: (val) => ~~(msgCount.val - msgCount.lastSecond.val)
        }
      }
    }),
    clients: new uikit.Stat({
      status: {
        inject: require('vjs/lib/operator/transform'),
        $transform: (val) => val ? 'ok' : 'error',
        val: connected
      },
      title: { text: 'Clients' },
      counter: {
        text: {
          inject: require('vjs/lib/operator/transform'),
          val: hub.get('clients', {}),
          $transform (val) {
            var cnt = 0
            val.each(() => cnt++)
            return cnt
          }
        }
      }
    })
  }
})

var updating = new Observable(false)
updating.on(function (data) {
  clearInterval(this._interval)
  this._interval = null
  if (this.val === true) {
    this._interval = setInterval(() => {
      hub.set({ text: (~~(Math.random() * 1000)) + ' from:' + uuid })
    }, 0)
  }
})

var fieldName = new Observable(1)

var addfields = new Observable(false)
addfields.on(function (data) {
  clearInterval(this._interval)
  this._interval = null
  if (this.val === true) {
    this._interval = setInterval(() => {
      hub.set({ [fieldName.val]: ~~(Math.random() * 999999) })
      fieldName.val++
    }, 0)
  }
})

app.holder.set({
  textfields: {
    ChildConstructor: uikit.Input,
    textField: {
      input: { text: hub.get('text', {}) }
    },
    textField2: {
      input: { text: hub.get('text2', {}) }
    }
  },
  button: new FireButton({ updating: updating }),
  addfield: {
    button: new uikit.Button({
      text: {
        val: 'add field: ',
        inject: require('vjs/lib/operator/add'),
        $add: fieldName
      },
      on: {
        click () {
          hub.set({ [fieldName.val]: ~~(Math.random() * 999999) })
          fieldName.val++
        }
      }
    })
  },
  addfields: new FireButton({ updating: addfields })
})

app.set({
  keysOverview: {
    css: 'labels',
    ChildConstructor: uikit.Badge
  }
})

for(var i = 0 ; i < 2000; i++) {
  hub.get(i+1+'', {})
}

hub.on('property', function (data, event) {
  if (data.added) {
    for (let i in data.added) {
      app.keysOverview.setKey(data.added[i], { message: { text: this[data.added[i]]} }, event)
    }
  }
  if (data.removed) {
    for (let i in data.removed) {
      app.keysOverview[data[i]] && app.keysOverview[data[i]].remove(event)
    }
  }
})

hub.each((property, key) => {
  app.keysOverview.setKey(key + 'init', { message: { text: property } })
})

exports.app = app
exports.hub = hub
<commit_msg>added fields overview<commit_after>'use strict'
require('./style.less')

var Element = require('element')
Element.prototype.inject(
  require('element/lib/property/text'),
  require('element/lib/property/transform'),
  require('element/lib/events/drag')
)
var Observable = require('vjs/lib/observable')
var Hub = require('../../lib')
var uikit = require('uikit')
var uuid = require('vjs/lib/util/uuid').val

var hub = global.hub = new Hub({
  adapter: {
    inject: require('../../lib/adapter/websocket'),
    on: {
      connection () {
        connected.val = true
        console.log('CONNECTION')
      },
      close () {
        connected.val = false
        console.log('close')
      },
      error (err) {
        console.error('err!', err.stack)
      }
    }
  },
  text: {
    on: {
      data (data) {
        msgCount.val++
      }
    }
  }
})

var start = Date.now()
var now = new Observable(0)
var connected = new Observable(false)
var msgCount = new Observable({
  val: 0,
  lastSecond: 0
})

setInterval(() => {
  now.val++
  msgCount.lastSecond.val = msgCount.val
}, 1000)

var FireButton = new uikit.Button({
  properties: {
    updating: function(val) {
      this._updating = val
      this.set({
        text: val,
        css: val
      })
    }
  },
  text: {
    inject: require('vjs/lib/operator/transform'),
    $transform: (val) => val === true ? 'Stop updates' : 'Fire updates'
  },
  css: {
    inject: require('vjs/lib/operator/transform'),
    $transform: (val) => val === true ? 'ui-button active' : 'ui-button inactive'
  },
  on: {
    click () {
      this._updating.val = !this._updating.val
    }
  }
}).Constructor

var app = global.app = new Element({
  node: document.body,
  rendered: true,
  css: 'app',
  holder: {
    labels: {
      ChildConstructor: uikit.Badge,
      uuid: {
        message: { text: uuid }
      },
      time: {
        message: {
          text: {
            val: now,
            inject: require('uikit/lib/transform/time')
          }
        }
      },
      upstream: new uikit.InputBadge({
        message: { text: hub.adapter }
      }),
      instance: new uikit.InputBadge({
        message: { text: hub.adapter.instance }
      }),
      clock: new uikit.Label({
        text: {
          val: start,
          inject: require('uikit/lib/transform/time')
        }
      })
    },
    msgcnt: new uikit.Stat({
      title: { text: 'Messages' },
      counter: {
        text: {
          inject: require('uikit/lib/transform/number'),
          val: msgCount
        }
      }
    }),
    msg: new uikit.Stat({
      title: { text: 'Msg/s' },
      counter: {
        text: {
          inject: require('vjs/lib/operator/transform'),
          val: now,
          $transform: (val) => ~~(msgCount.val - msgCount.lastSecond.val)
        }
      }
    }),
    clients: new uikit.Stat({
      status: {
        inject: require('vjs/lib/operator/transform'),
        $transform: (val) => val ? 'ok' : 'error',
        val: connected
      },
      title: { text: 'Clients' },
      counter: {
        text: {
          inject: require('vjs/lib/operator/transform'),
          val: hub.get('clients', {}),
          $transform (val) {
            var cnt = 0
            val.each(() => cnt++)
            return cnt
          }
        }
      }
    })
  }
})

var updating = new Observable(false)
updating.on(function (data) {
  clearInterval(this._interval)
  this._interval = null
  if (this.val === true) {
    this._interval = setInterval(() => {
      hub.set({ text: (~~(Math.random() * 1000)) + ' from:' + uuid })
    }, 0)
  }
})

var fieldName = new Observable(1)

var addfields = new Observable(false)
addfields.on(function (data) {
  clearInterval(this._interval)
  this._interval = null
  if (this.val === true) {
    this._interval = setInterval(() => {
      hub.set({ [fieldName.val]: ~~(Math.random() * 999999) })
      fieldName.val++
    }, 0)
  }
})

app.holder.set({
  textfields: {
    ChildConstructor: uikit.Input,
    textField: {
      input: { text: hub.get('text', {}) }
    },
    textField2: {
      input: { text: hub.get('text2', {}) }
    }
  },
  button: new FireButton({ updating: updating }),
  addfield: {
    button: new uikit.Button({
      text: {
        val: 'add field: ',
        inject: require('vjs/lib/operator/add'),
        $add: fieldName
      },
      on: {
        click () {
          hub.set({ [fieldName.val]: ~~(Math.random() * 999999) })
          fieldName.val++
        }
      }
    })
  },
  addfields: new FireButton({ updating: addfields })
})

app.set({
  keysOverview: {
    css: 'labels',
    ChildConstructor: uikit.Badge
  }
})

// for(var i = 0 ; i < 2000; i++) {
//   hub.get(i+1+'', {})
// }

hub.on('property', function (data, event) {
  if (data.added) {
    for (let i in data.added) {
      app.keysOverview.setKey(data.added[i], { message: { text: this[data.added[i]]} }, event)
    }
  }
  if (data.removed) {
    for (let i in data.removed) {
      app.keysOverview[data[i]] && app.keysOverview[data[i]].remove(event)
    }
  }
})

hub.each((property, key) => {
  app.keysOverview.setKey(key + 'init', { message: { text: property } })
})

exports.app = app
exports.hub = hub
<|endoftext|>


<commit_before>import React from 'react';

const HomePage = () => (

    Welcome home!

);

export default HomePage;
<commit_msg>Fetch data in home component<commit_after>import React from 'react';

export default class HomePage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      fetched: false,
      transactions: []
    };
  }

  componentDidMount() {
    window.setTimeout(() => {
      this.fetchData();
    }, 1000);
  }

  // We set unmounted so that we can ignore data requests
  componentWillUnmount () {
    this.unmounted = true;
  }

  fetchData() {
    fetch('/tests')
      .then(
        res => res.json()
      )
      .then(json => {
        // Only set the state if the component is still mounted
        if (this.unmounted) { return; }
        this.setState({
          fetched: true,
          transactions: json.data
        });
      })
      .catch(() => console.error('There was an error while retrieving data.'));
  }

  render() {
    return (

        {!this.state.fetched ? 'Loading...' : `Fetched ${this.state.transactions.length} items!`}

    );
  }
}

export default HomePage;
<|endoftext|>


<commit_before>/**
 * End2End test for admin survey module
 */

var gimsUtility = require('../../utility');

describe('admin/survey', function() {

    beforeEach(function() {
        browser.get('/admin/survey');
        gimsUtility.login(undefined, undefined, browser);
    });

    it('should display a grid containing surveys', function() {
        expect(element.all(by.css('[ng-view] [ng-grid]')).count()).toBe(1);
    });

    it('should contains a grid with more than 0 element', function() {
        expect(element.all(by.css('[ng-view] [ng-grid] .ngCanvas')).count()).toBeGreaterThan(0);
    });

    it('should contains a link for creating new survey', function() {
        expect(element.all(by.css('[ng-view] .link-new')).count()).toBe(1);
    });

    it('should lead to /admin/survey/new when following link new survey', function() {
        element(by.css('[ng-view] .link-new')).click();
        expect(browser.getCurrentUrl()).toMatch(browser.baseUrl + '/admin/survey/new');
    });
});

/**
 * End2End test for admin survey module
 */
describe('admin/survey/new', function() {

    beforeEach(function() {
        browser.get('/admin/survey/new');
        gimsUtility.login(undefined, undefined, browser);
    });

    var randomCode;

    function fillSurveyForm() {
        // Computes random code
        randomCode = Math.random().toString(36).substr(2, 4);
        element(by.model('survey.code')).sendKeys(randomCode);
        element(by.model('survey.name')).sendKeys('foo');
        element(by.model('survey.isActive')).element(by.css("[value='0']")).click();
        element(by.model('survey.year')).sendKeys('2013');
        element(by.model('survey.comments')).sendKeys('foo bar');
        element(by.model('survey.dateStart')).sendKeys('08/05/2013');
        element(by.model('survey.dateEnd')).sendKeys('08/05/2014');
    }

    it('should have tab "General" visible but *not* tabs "question", "questionnaires" and "users"', function() {
        var panes = [
            {text: 'General', visible: 1},
            {text: 'Questions', visible: 0},
            {text: 'Users', visible: 0},
            {text: 'Questionnaires', visible: 0}
        ];

        panes.forEach(function(pane) {
            expect(element.all(by.xpath("//*[@ng-view]//*[contains(@class, 'nav-tabs')]//li//a[text()='" + pane.text + "']")).count()).toBe(pane.visible);
        });
    });

    it('should be able to fill-in required fields', function() {
        expect(element.all(by.css('[ng-view] .btn-save[disabled]')).count()).toBe(1);
        expect(element.all(by.css('[ng-view] .btn-saving')).count()).toBe(0);

        fillSurveyForm();
        expect(element.all(by.css('[ng-view] .btn-save[disabled]')).count()).toBe(0);
    });

    it('should redirect to admin/survey/edit after survey created', function() {

        fillSurveyForm();

        // Click save button
        element(by.css('[ng-view] .btn-save')).click();

        // Check if the element was found in survey list
        expect(browser.getCurrentUrl()).toContain(browser.baseUrl + '/admin/survey/edit');
    });

    it('should be able to save a new survey and delete it', function() {

        fillSurveyForm();

        // Click save button
        element(by.css('[ng-view] .btn-save')).click();

        // Should redirect to edit URL
        browser.sleep(1);
        expect(browser.getCurrentUrl()).toMatch(/\/admin\/survey\/edit\/\d+/);

        // Should find the same value that we entered (reloaded from DB)
        expect(element(by.model('survey.code')).getAttribute('value')).toMatch(randomCode);

        // Delete the survey
        element(by.css('form > .btn.btn-danger')).click();
        element(by.css(".modal .btn-danger")).click();

        // Should redirect to survey list
        browser.sleep(1);
        expect(browser.getCurrentUrl()).toBe(browser.baseUrl + '/admin/survey');

        // The deleted survey shouldn't be in the list anymore
        element(by.css('[ng-view] [ng-grid]')).all(by.xpath('span[text() = "' + randomCode + '"]')).then(function(elements) {
            expect(elements.length).toBe(0);
        });
    });
});

/**
 * End2End test for admin survey module
 */
describe('admin/survey/edit', function() {

    beforeEach(function() {
        browser.get('/admin/survey/edit/1');
        gimsUtility.login(undefined, undefined, browser);
    });

    it('should have tabs "General", "question", "questionnaires" and "users"', function() {
        var panes = [
            {text: 'General', visible: 1},
            {text: 'Questions', visible: 1},
            {text: 'Questionnaires', visible: 1},
            {text: 'Users', visible: 1}
        ];
        panes.forEach(function(pane) {
            expect(element.all(by.xpath("//*[@ng-view]//*[contains(@class, 'nav-tabs')]//li//a[text()='" + pane.text + "']")).count()).toBe(pane.visible);
        });
    });
});

/**
 * End2End test for admin survey module
 */
describe('admin/questionnaire/new', function() {

    beforeEach(function() {
        browser.get('/admin/questionnaire/new?survey=23');
        gimsUtility.login(undefined, undefined, browser);
    });

    function getSelect2FirstItem(select2Id) {
        element(by.css('div#s2id_' + select2Id)).click();
        var item = element(by.css('.select2-result-selectable:first-child'));

        return item;
    }

    var selectedCountry;
    function fillQuestionnaireForm() {
        getSelect2FirstItem('autogen1').then(function(country) {
            country.getText().then(function(countryName) {
                selectedCountry = countryName;
                country.click();
            });
        });
        element(by.model('questionnaire.dateObservationStart')).sendKeys('08/05/2013');
        element(by.model('questionnaire.dateObservationEnd')).sendKeys('08/05/2014');
        element(by.model('questionnaire.comments')).sendKeys('foo bar');
    }

    it('should have tab "General" visible but *not* tab "users"', function() {
        var panes = [
            {text: 'General', visible: 1},
            {text: 'Questionnaires', visible: 0}
        ];

        panes.forEach(function(pane) {
            expect(element.all(by.xpath("//*[@ng-view]//*[contains(@class, 'nav-tabs')]//li//a[text()='" + pane.text + "']")).count()).toBe(pane.visible);
        });
    });

    it('should be able to fill-in required fields', function() {
        expect(element.all(by.css('[ng-view] .btn-save[disabled]')).count()).toBe(1);
        expect(element.all(by.css('[ng-view] .btn-saving')).count()).toBe(0);

        fillQuestionnaireForm();
        expect(element.all(by.css('[ng-view] .btn-save[disabled]')).count()).toBe(0);
    });

    it('should redirect to admin/survey/edit after question created', function() {

        fillQuestionnaireForm();

        // Click save button
        element(by.css('[ng-view] .btn-save')).click();

        // Check if the element was found in survey list
        expect(browser.getCurrentUrl()).toContain(browser.baseUrl + '/admin/questionnaire/edit');
    });

    it('should be able to save a new questionnaire and delete it', function() {

        fillQuestionnaireForm();

        // Click save button
        element(by.css('[ng-view] .btn-save')).click();

        // Should redirect to edit URL
        expect(browser.getCurrentUrl()).toMatch(/\/admin\/questionnaire\/edit\/\d+/);

        // Should find the same value that we entered (reloaded from DB)
        expect(element(by.model('questionnaire.comments')).getAttribute('value')).toMatch('foo bar');

        // Delete the questionnaire
        element(by.css('form > .btn.btn-danger')).click();
        element(by.css('.modal .btn-danger')).click();

        // Should redirect to questionnaire list
        expect(browser.getCurrentUrl()).toContain(browser.baseUrl + '/admin/survey/edit/23');

        element(by.xpath("//*[@ng-view]//*[contains(@class, 'nav-tabs')]//li//a[text()='Questionnaires']")).click();

        // The deleted questionnaire shouldn't be in the list anymore
        element(by.css('[gims-grid-questionnaire] [ng-grid]')).all(by.xpath('span[text() = "' + selectedCountry + '"]')).then(function(elements) {
            expect(elements.length).toBe(0);
        });
    });
});

//@todo test create new questionnaire
//@todo test create new question
//@todo test create new users
<commit_msg>Fix e2e tests<commit_after>/**
 * End2End test for admin survey module
 */

var gimsUtility = require('../../utility');

describe('admin/survey', function() {

    beforeEach(function() {
        browser.get('/admin/survey');
        gimsUtility.login(undefined, undefined, browser);
    });

    it('should display a grid containing surveys', function() {
        expect(element.all(by.css('[ng-view] [ng-grid]')).count()).toBe(1);
    });

    it('should contains a grid with more than 0 element', function() {
        expect(element.all(by.css('[ng-view] [ng-grid] .ngCanvas')).count()).toBeGreaterThan(0);
    });

    it('should contains a link for creating new survey', function() {
        expect(element.all(by.css('[ng-view] .link-new')).count()).toBe(1);
    });

    it('should lead to /admin/survey/new when following link new survey', function() {
        element(by.css('[ng-view] .link-new')).click();
        expect(browser.getCurrentUrl()).toMatch(browser.baseUrl + '/admin/survey/new');
    });
});

/**
 * End2End test for admin survey module
 */
describe('admin/survey/new', function() {

    beforeEach(function() {
        browser.get('/admin/survey/new');
        gimsUtility.login(undefined, undefined, browser);
    });

    var randomCode;

    function fillSurveyForm() {
        // Computes random code
        randomCode = Math.random().toString(36).substr(2, 4);
        element(by.model('survey.code')).sendKeys(randomCode);
        element(by.model('survey.name')).sendKeys('foo');
        element(by.model('survey.isActive')).element(by.css("[value='0']")).click();
        element(by.model('survey.year')).sendKeys('2013');
        element(by.model('survey.comments')).sendKeys('foo bar');
        element(by.model('survey.dateStart')).sendKeys('08/05/2013');
        element(by.model('survey.dateEnd')).sendKeys('08/05/2014');
    }

    it('should have tab "General" visible but *not* tabs "question", "questionnaires" and "users"', function() {
        var panes = [
            {text: 'General', visible: 1},
            {text: 'Questions', visible: 0},
            {text: 'Users', visible: 0},
            {text: 'Questionnaires', visible: 0}
        ];

        panes.forEach(function(pane) {
            expect(element.all(by.xpath("//*[@ng-view]//*[contains(@class, 'nav-tabs')]//li//a[text()='" + pane.text + "']")).count()).toBe(pane.visible);
        });
    });

    it('should be able to fill-in required fields', function() {
        expect(element.all(by.css('[ng-view] .btn-save[disabled]')).count()).toBe(1);
        expect(element.all(by.css('[ng-view] .btn-saving')).count()).toBe(0);

        fillSurveyForm();
        expect(element.all(by.css('[ng-view] .btn-save[disabled]')).count()).toBe(0);
    });

    it('should redirect to admin/survey/edit after survey created', function() {

        fillSurveyForm();

        // Click save button
        element(by.css('[ng-view] .btn-save')).click();

        // Check if the element was found in survey list
        expect(browser.getCurrentUrl()).toContain(browser.baseUrl + '/admin/survey/edit');
    });

    it('should be able to save a new survey and delete it', function() {

        fillSurveyForm();

        // Click save button
        element(by.css('[ng-view] .btn-save')).click();

        // Should redirect to edit URL
        browser.sleep(1);
        expect(browser.getCurrentUrl()).toMatch(/\/admin\/survey\/edit\/\d+/);

        // Should find the same value that we entered (reloaded from DB)
        expect(element(by.model('survey.code')).getAttribute('value')).toMatch(randomCode);

        // Delete the survey
        element(by.css('form > .btn.btn-danger')).click();
        element(by.css(".modal .btn-danger")).click();

        // Should redirect to survey list
        browser.sleep(1);
        // TODO remove the '#3' this is a bug in angular-bootstrap: https://github.com/angular-ui/bootstrap/issues/2155
        expect(browser.getCurrentUrl()).toBe(browser.baseUrl + '/admin/survey#3');

        // The deleted survey shouldn't be in the list anymore
        element(by.css('[ng-view] [ng-grid]')).all(by.xpath('span[text() = "' + randomCode + '"]')).then(function(elements) {
            expect(elements.length).toBe(0);
        });
    });
});

/**
 * End2End test for admin survey module
 */
describe('admin/survey/edit', function() {

    beforeEach(function() {
        browser.get('/admin/survey/edit/1');
        gimsUtility.login(undefined, undefined, browser);
    });

    it('should have tabs "General", "question", "questionnaires" and "users"', function() {
        var panes = [
            {text: 'General', visible: 1},
            {text: 'Questions', visible: 1},
            {text: 'Questionnaires', visible: 1},
            {text: 'Users', visible: 1}
        ];
        panes.forEach(function(pane) {
            expect(element.all(by.xpath("//*[@ng-view]//*[contains(@class, 'nav-tabs')]//li//a[text()='" + pane.text + "']")).count()).toBe(pane.visible);
        });
    });
});

/**
 * End2End test for admin survey module
 */
describe('admin/questionnaire/new', function() {

    beforeEach(function() {
        browser.get('/admin/questionnaire/new?survey=23');
        gimsUtility.login(undefined, undefined, browser);
    });

    function getSelect2FirstItem(select2Id) {
        element(by.css('div#s2id_' + select2Id)).click();
        var item = element(by.css('.select2-result-selectable:first-child'));

        return item;
    }

    var selectedCountry;
    function fillQuestionnaireForm() {
        getSelect2FirstItem('autogen1').then(function(country) {
            country.getText().then(function(countryName) {
                selectedCountry = countryName;
                country.click();
            });
        });
        element(by.model('questionnaire.dateObservationStart')).sendKeys('08/05/2013');
        element(by.model('questionnaire.dateObservationEnd')).sendKeys('08/05/2014');
        element(by.model('questionnaire.comments')).sendKeys('foo bar');
    }

    it('should have tab "General" visible but *not* tab "users"', function() {
        var panes = [
            {text: 'General', visible: 1},
            {text: 'Questionnaires', visible: 0}
        ];

        panes.forEach(function(pane) {
            expect(element.all(by.xpath("//*[@ng-view]//*[contains(@class, 'nav-tabs')]//li//a[text()='" + pane.text + "']")).count()).toBe(pane.visible);
        });
    });

    it('should be able to fill-in required fields', function() {
        expect(element.all(by.css('[ng-view] .btn-save[disabled]')).count()).toBe(1);
        expect(element.all(by.css('[ng-view] .btn-saving')).count()).toBe(0);

        fillQuestionnaireForm();
        expect(element.all(by.css('[ng-view] .btn-save[disabled]')).count()).toBe(0);
    });

    it('should redirect to admin/survey/edit after question created', function() {

        fillQuestionnaireForm();

        // Click save button
        element(by.css('[ng-view] .btn-save')).click();

        // Check if the element was found in survey list
        expect(browser.getCurrentUrl()).toContain(browser.baseUrl + '/admin/questionnaire/edit');
    });

    it('should be able to save a new questionnaire and delete it', function() {

        fillQuestionnaireForm();

        // Click save button
        element(by.css('[ng-view] .btn-save')).click();

        // Should redirect to edit URL
        expect(browser.getCurrentUrl()).toMatch(/\/admin\/questionnaire\/edit\/\d+/);

        // Should find the same value that we entered (reloaded from DB)
        expect(element(by.model('questionnaire.comments')).getAttribute('value')).toMatch('foo bar');

        // Delete the questionnaire
        element(by.css('form > .btn.btn-danger')).click();
        element(by.css('.modal .btn-danger')).click();

        // Should redirect to questionnaire list
        expect(browser.getCurrentUrl()).toContain(browser.baseUrl + '/admin/survey/edit/23');

        element(by.xpath("//*[@ng-view]//*[contains(@class, 'nav-tabs')]//li//a[text()='Questionnaires']")).click();

        // The deleted questionnaire shouldn't be in the list anymore
        element(by.css('[gims-grid-questionnaire] [ng-grid]')).all(by.xpath('span[text() = "' + selectedCountry + '"]')).then(function(elements) {
            expect(elements.length).toBe(0);
        });
    });
});

//@todo test create new questionnaire
//@todo test create new question
//@todo test create new users
<|endoftext|>