<commit_before>/*jlint node: true */
/*global require, console, __dirname, module, setInterval, clearInterval */

/*
 * jenkins.js
 *
 * Copyright (C) 2015 by James Jenner
 *
 * 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.
 *
 * Note that this uses the Jenkins SDK.JavaScript, refer to resources mentioned
 * below for further information about the Jenkins SDK for javascript.
 */

var EventEmitter = require('events').EventEmitter;
var util         = require('util');
var async        = require('async');

var jenkinsapi = require('./jenkins/jenkins');

var JenkinsState = require('../shared/jenkinsState.js');

module.exports = Jenkins;

util.inherits(Jenkins, EventEmitter);

Jenkins.DEFAULT_POLL_MINS = 1;
Jenkins.DEFAULT_NAME = 'kitchen_ellipse';

Jenkins.EVENT_DATA_RECEIVED = "dataReceived";

function Jenkins(options) {
  EventEmitter.call(this);

  this.host = ((options.host !== null && options.host !== undefined) ? options.host : 'http://awsjenkins.ventyx.abb.com:8080');
  this.name = ((options.name !== null && options.name !== undefined) ? options.name : Jenkins.DEFAULT_NAME);

  this.debug = false;
  this.pollFrequencyMinutes = ((options.pollFrequencyMinutes !== null && options.pollFrequencyMinutes !== undefined) ? options.pollFrequencyMinutes : Jenkins.DEFAULT_POLL_MINS);
  this.pollFrequencyMinutes = 0.5;
  this.pollFrequencyMilliseconds = this.pollFrequencyMinutes * 60 * 1000;
  // TODO: stop this from being hard coded
  this.maxHistory = 5;
  this.history = [];

  this.jenkinsState = new JenkinsState();
}

Jenkins.prototype.startMonitor = function () {
  if(this.debug) {
    console.log("Jenkins.startMonitor -> " + this.name);
  }

  if (this.host === '' || this.name === '') {
    return;
  }

  this.jenkins = jenkinsapi.init(this.host);

  this._monitor();
};

Jenkins.prototype._monitor = function () {
  // TODO: change to setTimeout?
  // in prod poll interval should be larger than time to fetch, however cannot garentee

  this.sprintMontiorInterval = setInterval(function() {
    this._monitorExecute();
  }.bind(this), this.pollFrequencyMilliseconds);
};

Jenkins.prototype._monitorExecute = function () {

  this.jenkins.job_info('/' + this.name, function(err, data) {
    if(err) {
      console.log("ERROR (job info kitchen_ellipse): " + err);
      return;
    }

    this.jenkinsState = new JenkinsState();
    this.jenkinsState.displayName = data.displayName;
    this.jenkinsState.description = data.description;
    this.jenkinsState.name = data.name;
    this.jenkinsState.buildable = data.buildable;
    this.jenkinsState.healthScore = data.healthReport[0].score;
    this.jenkinsState.healthDescription = data.healthReport[0].description;

    if(this.debug) {
      console.log("\t display name: " + data.displayName);
      console.log("\t  description: " + data.description);
      console.log("\t         name: " + data.name);
      console.log("\t          url: " + data.url);
      console.log("\t    buildable: " + data.buildable);
      console.log("\t        color: " + data.color);
      console.log("\tHealth Report: " + data.healthReport[0].description);
      console.log("\t     icon URL: " + data.healthReport[0].iconUrl);
      console.log("\t        score: " + data.healthReport[0].score);
      console.log("\t       builds: ");
    }

    // increase by 1 as if build is in progress then it's in the job results
    var maxBuilds = this.maxHistory + 1;
    var isLastBuild = false;
    data.builds.sort(compareJenkinsNumber);
    var processBuilds = [];

    for(var i = 0; i < data.builds.length && i < maxBuilds; i++) {
      processBuilds.push(data.builds[i].number);
    }

    async.map(processBuilds, this._getJobResult.bind(this), this._buildDetailsReceived.bind(this));
  }.bind(this));
};

Jenkins.prototype._getJobResult = function (jobNbr, done) {
  this.jenkins.build_info('/' + this.name, jobNbr, function(err, data) {
    if(!err) {
      if(data.building) {
        return done(null, {buildNbr: jobNbr, result: data.result, building: data.building, progress: Math.round((new Date().getTime() - data.timestamp) / data.estimatedDuration * 100)});
      } else {
        return done(null, {buildNbr: jobNbr, result: data.result, building: data.building, progress: 0});
      }
    } else {
      return done(err);
    }
  });
};

Jenkins.prototype._getBuildDetails = function(buildNbr, isLastBuild) {
};

Jenkins.prototype._buildDetailsReceived = function(err, result) {

  for(var i = 0; i < result.length; i++) {
    if(result[i].building) {
      if(this.debug) {
        console.log("\t               " + result[i].buildNbr + " -> " + result[i].progress + "%");
      }
      this.jenkinsState.building = true;
      this.jenkinsState.buildingNumber = result[i].buildNbr;
      this.jenkinsState.progress = result[i].progress;
    } else {
      if(this.debug) {
        console.log("\t               " + result[i].buildNbr + " : " + result[i].result);
      }
      this.jenkinsState.builds.push({buildNumber: result[i].buildNbr, result: result[i].result});
    }
  }
  this._processResults();
};

Jenkins.prototype._processResults = function () {
  var i = 0;
  var j = 0;
  var exists = false;
  var newBuilds = [];

  this.jenkinsState.builds.sort(compareBuilds);

  for (i = 0; i < this.jenkinsState.builds.length; i++) {
    exists = false;
    for (j = 0; j < this.history.length && !exists; j++) {
      if(this.history[j].buildNumber === this.jenkinsState.builds[i].buildNumber) {
        exists = true;
      }
    }

    if(!exists) {
      if(this.history.length > this.maxHistory) {
        this.history.shift();
      }

      this.history.push(this.jenkinsState.builds[i]);
      newBuilds.push(this.jenkinsState.builds[i]);
    }
  }

  this.jenkinsState.builds = newBuilds;
  this.jenkinsState.mostRecentBuildNumber = this.history[this.history.length - 1].buildNumber;
  this.jenkinsState.mostRecentBuildState = this.history[this.history.length - 1].result;
  if(this.jenkinsState.building) {
    this.jenkinsState.mostRecentBuildNumber = this.jenkinsState.buildingNumber;
    this.jenkinsState.mostRecentBuildState = '';
  }

  // sort the
  this.emit(Jenkins.EVENT_DATA_RECEIVED, this.name, this.jenkinsState);
};

Jenkins.prototype.stopMonitor = function(type) {
  this._stopMonitor(this.sprintMontiorInterval);
};

Jenkins.prototype._stopMonitor = function(interval) {
  if(interval !== undefined && interval !== null) {
    clearInterval(interval);
  }
};

function Job(value, color) {
  this.color = color;
  this.value = value;
}

function compareJenkinsNumber (a, b) {
  if (a.number < b.number) {
     return 1;
  }

  if (a.number > b.number) {
    return -1;
  }

  return 0;
}

function compareBuilds (a, b) {
  if (a.buildNumber < b.buildNumber) {
     return -1;
  }

  if (a.buildNumber > b.buildNumber) {
    return 1;
  }

  return 0;
}<commit_msg>Replaced for with forEach due to potential sparse array<commit_after>/*jlint node: true */
/*global require, console, __dirname, module, setInterval, clearInterval */

/*
 * jenkins.js
 *
 * Copyright (C) 2015 by James Jenner
 *
 * 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.
 *
 * Note that this uses the Jenkins SDK.JavaScript, refer to resources mentioned
 * below for further information about the Jenkins SDK for javascript.
 */

var EventEmitter = require('events').EventEmitter;
var util         = require('util');
var async        = require('async');

var jenkinsapi = require('./jenkins/jenkins');

var JenkinsState = require('../shared/jenkinsState.js');

module.exports = Jenkins;

util.inherits(Jenkins, EventEmitter);

Jenkins.DEFAULT_POLL_MINS = 1;
Jenkins.DEFAULT_NAME = 'kitchen_ellipse';

Jenkins.EVENT_DATA_RECEIVED = "dataReceived";

function Jenkins(options) {
  EventEmitter.call(this);

  this.host = ((options.host !== null && options.host !== undefined) ? options.host : 'http://awsjenkins.ventyx.abb.com:8080');
  this.name = ((options.name !== null && options.name !== undefined) ? options.name : Jenkins.DEFAULT_NAME);

  this.debug = false;
  this.pollFrequencyMinutes = ((options.pollFrequencyMinutes !== null && options.pollFrequencyMinutes !== undefined) ? options.pollFrequencyMinutes : Jenkins.DEFAULT_POLL_MINS);
  this.pollFrequencyMinutes = 0.5;
  this.pollFrequencyMilliseconds = this.pollFrequencyMinutes * 60 * 1000;
  // TODO: stop this from being hard coded
  this.maxHistory = 5;
  this.history = [];

  this.jenkinsState = new JenkinsState();
}

Jenkins.prototype.startMonitor = function () {
  if(this.debug) {
    console.log("Jenkins.startMonitor -> " + this.name);
  }

  if (this.host === '' || this.name === '') {
    return;
  }

  this.jenkins = jenkinsapi.init(this.host);

  this._monitor();
};

Jenkins.prototype._monitor = function () {
  // TODO: change to setTimeout?
  // in prod poll interval should be larger than time to fetch, however cannot garentee

  this.sprintMontiorInterval = setInterval(function() {
    this._monitorExecute();
  }.bind(this), this.pollFrequencyMilliseconds);
};

Jenkins.prototype._monitorExecute = function () {

  this.jenkins.job_info('/' + this.name, function(err, data) {
    if(err) {
      console.log("ERROR (job info kitchen_ellipse): " + err);
      return;
    }

    this.jenkinsState = new JenkinsState();
    this.jenkinsState.displayName = data.displayName;
    this.jenkinsState.description = data.description;
    this.jenkinsState.name = data.name;
    this.jenkinsState.buildable = data.buildable;
    this.jenkinsState.healthScore = data.healthReport[0].score;
    this.jenkinsState.healthDescription = data.healthReport[0].description;

    if(this.debug) {
      console.log("\t display name: " + data.displayName);
      console.log("\t  description: " + data.description);
      console.log("\t         name: " + data.name);
      console.log("\t          url: " + data.url);
      console.log("\t    buildable: " + data.buildable);
      console.log("\t        color: " + data.color);
      console.log("\tHealth Report: " + data.healthReport[0].description);
      console.log("\t     icon URL: " + data.healthReport[0].iconUrl);
      console.log("\t        score: " + data.healthReport[0].score);
      console.log("\t       builds: ");
    }

    // increase by 1 as if build is in progress then it's in the job results
    var maxBuilds = this.maxHistory + 1;
    var isLastBuild = false;
    data.builds.sort(compareJenkinsNumber);
    var processBuilds = [];

    for(var i = 0; i < data.builds.length && i < maxBuilds; i++) {
      processBuilds.push(data.builds[i].number);
    }

    async.map(processBuilds, this._getJobResult.bind(this), this._buildDetailsReceived.bind(this));
  }.bind(this));
};

Jenkins.prototype._getJobResult = function (jobNbr, done) {
  this.jenkins.build_info('/' + this.name, jobNbr, function(err, data) {
    if(!err) {
      if(data.building) {
        return done(null, {buildNbr: jobNbr, result: data.result, building: data.building, progress: Math.round((new Date().getTime() - data.timestamp) / data.estimatedDuration * 100)});
      } else {
        return done(null, {buildNbr: jobNbr, result: data.result, building: data.building, progress: 0});
      }
    } else {
      return done(err);
    }
  });
};

Jenkins.prototype._getBuildDetails = function(buildNbr, isLastBuild) {
};

Jenkins.prototype._buildDetailsReceived = function(err, result) {
  result.forEach(function(item, index) {
    if(item.building) {
      if(this.debug) {
        console.log("\t               " + item.buildNbr + " -> " + item.progress + "%");
      }
      this.jenkinsState.building = true;
      this.jenkinsState.buildingNumber = item.buildNbr;
      this.jenkinsState.progress = item.progress;
    } else {
      if(this.debug) {
        console.log("\t               " + item.buildNbr + " : " + item.result);
      }
      this.jenkinsState.builds.push({buildNumber: item.buildNbr, result: item.result});
    }
  }.bind(this));

  this._processResults();
};

Jenkins.prototype._processResults = function () {
  var i = 0;
  var j = 0;
  var exists = false;
  var newBuilds = [];

  this.jenkinsState.builds.sort(compareBuilds);

  for (i = 0; i < this.jenkinsState.builds.length; i++) {
    exists = false;
    for (j = 0; j < this.history.length && !exists; j++) {
      if(this.history[j].buildNumber === this.jenkinsState.builds[i].buildNumber) {
        exists = true;
      }
    }

    if(!exists) {
      if(this.history.length > this.maxHistory) {
        this.history.shift();
      }

      this.history.push(this.jenkinsState.builds[i]);
      newBuilds.push(this.jenkinsState.builds[i]);
    }
  }

  this.jenkinsState.builds = newBuilds;
  this.jenkinsState.mostRecentBuildNumber = this.history[this.history.length - 1].buildNumber;
  this.jenkinsState.mostRecentBuildState = this.history[this.history.length - 1].result;
  if(this.jenkinsState.building) {
    this.jenkinsState.mostRecentBuildNumber = this.jenkinsState.buildingNumber;
    this.jenkinsState.mostRecentBuildState = '';
  }

  // sort the
  this.emit(Jenkins.EVENT_DATA_RECEIVED, this.name, this.jenkinsState);
};

Jenkins.prototype.stopMonitor = function(type) {
  this._stopMonitor(this.sprintMontiorInterval);
};

Jenkins.prototype._stopMonitor = function(interval) {
  if(interval !== undefined && interval !== null) {
    clearInterval(interval);
  }
};

function Job(value, color) {
  this.color = color;
  this.value = value;
}

function compareJenkinsNumber (a, b) {
  if (a.number < b.number) {
     return 1;
  }

  if (a.number > b.number) {
    return -1;
  }

  return 0;
}

function compareBuilds (a, b) {
  if (a.buildNumber < b.buildNumber) {
     return -1;
  }

  if (a.buildNumber > b.buildNumber) {
    return 1;
  }

  return 0;
}<|endoftext|>


<commit_before>;

function disable_field_based_on_value(field, value) {
    if (field.val() == value) {
        field.attr('disabled', 'disabled')
    }
}

function show_or_hide_attribute_fields(attribute_value){
    if(attribute_value == 'value'){
        $('#id_validate_with_question').hide();
        $('#id_value').show();
    }
    if(attribute_value == 'validate_with_question')
    {
        $('#id_validate_with_question').show();
        $('#id_value').hide();
    }
}
function show_or_hide_next_question(action_value) {
    show_next_question = ['SKIP_TO', 'ASK_SUBQUESTION'];

    if (show_next_question.indexOf(action_value) != -1) {
        $('#id_next_question').show()
    }
    else {
        $('#id_next_question').hide()
    }
}

function append_to_drop_down_options(url)
{
    counter=0;
    $.get( url, function( data ) {
        $.each(data, function() {
            $('#id_next_question').append("<option value=" + data[counter]['id'] + ">" + data[counter]['text'] +"</option>");
            counter++;
        });
    });
    }

function replace_next_question_with_right_data(questions_url) {
    if(questions_url != ""){
    $('#id_next_question').find('option')
        .remove()
        .end()
    }
    append_to_drop_down_options(questions_url)
}

function fill_questions_or_subquestions_in_next_question_field(action_value){
    var show_questions = ['SKIP_TO'];
    var show_sub_questions = ['ASK_SUBQUESTION'];

    var question_id = $('#id_question').val();
    var questions_url = "";

    if(show_questions.indexOf(action_value) != -1)
    {
        questions_url = '/questions/' + question_id +'/questions_json/'
    }
    else if (show_sub_questions.indexOf(action_value) != -1)
    {
        questions_url = '/questions/' + question_id +'/sub_questions_json/'
    }
    replace_next_question_with_right_data(questions_url);
}

jQuery(function($){
    var condition = $('#id_condition');
    var condition_value = 'EQUALS_OPTION';
    var attribute = $('#id_attribute');
    var attribute_value = 'option';
    var action_value = $('#id_action');

    disable_field_based_on_value(condition, condition_value);
    disable_field_based_on_value(attribute, attribute_value);
    show_or_hide_attribute_fields(attribute.val());
    show_or_hide_next_question(action_value.val());

    action_value.on('change', function(){
        show_or_hide_next_question($(this).val());
        fill_questions_or_subquestions_in_next_question_field(action_value.val());
    });

    attribute.on('change', function(){
        show_or_hide_attribute_fields(attribute.val());
    });

});<commit_msg>Brain/Pooja: Fixing post of disabled fields<commit_after>;

function disable_field_based_on_value(field, value) {
    if (field.val() == value) {
        field.attr('disabled', 'disabled')
    }
}

function show_or_hide_attribute_fields(attribute_value){
    var validate_with_question_field = $('#id_validate_with_question');
    var value_field = $('#id_value');

    if(attribute_value == 'value'){
        validate_with_question_field.hide();
        validate_with_question_field.attr('disabled', 'disabled');
        value_field.show();
        value_field.attr('disabled', false);
    }
    if(attribute_value == 'validate_with_question')
    {
        validate_with_question_field.show();
        validate_with_question_field.attr('disabled', false);
        value_field.hide();
        value_field.attr('disabled', 'disabled');
    }
}
function show_or_hide_next_question(action_value) {
    show_next_question = ['SKIP_TO', 'ASK_SUBQUESTION'];

    var next_question_field = $('#id_next_question');

    if (show_next_question.indexOf(action_value) != -1) {
        next_question_field.show();
        next_question_field.attr('disabled', false)
    }
    else {
        next_question_field.hide();
        next_question_field.attr('disabled', 'disabled')
    }
}

function append_to_drop_down_options(url)
{
    counter=0;
    $.get( url, function( data ) {
        $.each(data, function() {
            $('#id_next_question').append("<option value=" + data[counter]['id'] + ">" + data[counter]['text'] +"</option>");
            counter++;
        });
    });
    }

function replace_next_question_with_right_data(questions_url) {
    if(questions_url != ""){
    $('#id_next_question').find('option')
        .remove()
        .end()
    }
    append_to_drop_down_options(questions_url)
}

function fill_questions_or_subquestions_in_next_question_field(action_value){
    var show_questions = ['SKIP_TO'];
    var show_sub_questions = ['ASK_SUBQUESTION'];

    var question_id = $('#id_question').val();
    var questions_url = "";

    if(show_questions.indexOf(action_value) != -1)
    {
        questions_url = '/questions/' + question_id +'/questions_json/'
    }
    else if (show_sub_questions.indexOf(action_value) != -1)
    {
        questions_url = '/questions/' + question_id +'/sub_questions_json/'
    }
    replace_next_question_with_right_data(questions_url);
}

jQuery(function($){
    var condition = $('#id_condition');
    var condition_value = 'EQUALS_OPTION';
    var attribute = $('#id_attribute');
    var attribute_value = 'option';
    var action_value = $('#id_action');

    disable_field_based_on_value(condition, condition_value);
    disable_field_based_on_value(attribute, attribute_value);
    show_or_hide_attribute_fields(attribute.val());
    show_or_hide_next_question(action_value.val());

    action_value.on('change', function(){
        show_or_hide_next_question($(this).val());
        fill_questions_or_subquestions_in_next_question_field(action_value.val());
    });

    attribute.on('change', function(){
        show_or_hide_attribute_fields(attribute.val());
    });

});<|endoftext|>


<commit_before><commit_msg>Update project what-input to v1.2.0<commit_after><|endoftext|>


<commit_before>async function remindmeArgless (msg) {
  const prefix = this.db.getPrefix(msg.channel.guild ? msg.channel.guild.id : null);

  const delarray = [];
  const cleanup = async () => {
    if (msg.channel.type === 0 && msg.channel.permissionsOf(this.client.user.id).has('manageMessages')) {
      msg.channel.deleteMessages(delarray);
    }
  };

  delarray.push(msg.id);

  const collector = new this.utils.MessageCollector(
    this.client,
    msg.channel,
    (message) => message.author.id === msg.author.id,
    { time: 60000 }
  );
  let step = 1;
  const reminder = {};

  this.sendMessage(msg.channel.id, 'What would you like the reminder to be? (You can send `cancel` at any time to cancel creation.)')
    .then(m => delarray.push(m.id));

  collector.on('message', async m => {
    if (m.content.length === 0 && !m.attachments[0]) {
      return;
    }
    if (m.content.startsWith(`${prefix}remind`) || m.content.includes(`${this.client.user.id}> remind`)) {
      cleanup();
      return collector.stop();
    }
    if (m.content.toLowerCase().includes('cancel') || m.content.toLowerCase() === 'c') {
      this.sendMessage(msg.channel.id, 'Cancelled.');
      return collector.stop();
    }

    delarray.push(m.id);

    if (step === 1) {
      reminder.reminder = m.content || m.attachments[0].proxy_url;

      this.sendMessage(msg.channel.id, 'When would you like to be reminded? (e.g. 24 hours)')
        .then(m => delarray.push(m.id));
    }

    if (step === 2) {
      const parsedTime = this.utils.parseTime(m.content);

      if (parsedTime === 'INVALID') {
        return this.sendMessage(msg.channel.id, 'Invalid time argument. When would you like to be reminded? (e.g. `12 hours` or `next week`).')
          .then(m => delarray.push(m.id));
      }
      if (parsedTime === 'SET_FOR_PAST') {
        return this.sendMessage(msg.channel.id, 'Your reminder wasn\'t added because it was set for the past. Note that if you\'re trying to set a reminder for the same day at a specific time (e.g. `6 PM`), UTC time will be assumed. You can fix this by including your timezone (e.g. `6 PM PST`).\n\nWhen would you like to be reminded? (e.g. `12 hours` or `next week`).')
          .then(m => delarray.push(m.id));
      }

      reminder.dueDate = parsedTime.absolute;
      this.sendMessage(msg.channel.id, 'Would you like to receive the reminder in a specific channel, or in your DMs?\nMention the channel you\'d like to receive the reminder in, or send `DM` if you\'d like to receive it in your DMs.')
        .then(m => delarray.push(m.id));
    }

    if (step === 3) {
      if (!m.content.toLowerCase().startsWith('dm')) {
        if (!m.channelMentions[0] && !m.content.includes('here')) {
          return this.sendMessage(msg.channel.id, 'You need to either ping the channel you\'d like to receive your reminder in, send `here` or send `DM`.\nWhere would you like to receive your reminder?')
            .then(m => delarray.push(m.id));
        }
        reminder.channelID = m.channelMentions[0] || m.channel.id;
      }

      collector.stop();

      return this.sendMessage(msg.channel.id, JSON.stringify(reminder, '', '  '));

      await Bot.db.run(`INSERT INTO reminders (owner, reminderText, createdDate, duration, recurring, dueDate, channelID)
          VALUES (?, ?, ?, ?, ?, ?, ?);`, msg.author.id, r.reminderText, Date.now(), r.duration, r.recurring, r.dueDate, r.channelID);

      Bot.sendMessage(msg.channel.id, { embed: {
        color: Bot.config.embedColor,
        description: `:ballot_box_with_check: Reminder added: ${r.reminderText}`,
        footer: { text: 'Reminder set for ' },
        timestamp: new Date(r.dueDate)
      }});
      cleanup();
    }
    step++;
  });

  collector.on('end', async (_, reason) => {
    if (reason === 'time') {
      Bot.sendMessage(msg.channel.id, 'Prompt timed out.');
    }
  });
}

module.exports = remindmeArgless;<commit_msg>add recurring step, finish command<commit_after>async function remindmeArgless (msg) {
  const prefix = this.db.getPrefix(msg.channel.guild ? msg.channel.guild.id : null);

  const delarray = [];
  const cleanup = async () => {
    if (msg.channel.type === 0 && msg.channel.permissionsOf(this.client.user.id).has('manageMessages')) {
      msg.channel.deleteMessages(delarray);
    }
  };

  delarray.push(msg.id);

  const collector = new this.utils.MessageCollector(
    this.client,
    msg.channel,
    (message) => message.author.id === msg.author.id,
    { time: 60000 }
  );
  let step = 1;
  const reminder = { ownerID: msg.author.id };

  this.sendMessage(msg.channel.id, 'What would you like the reminder to be? (You can send `cancel` at any time to cancel creation.)')
    .then(m => delarray.push(m.id));

  collector.on('message', async m => {
    if (m.content.length === 0 && !m.attachments[0]) {
      return;
    }
    if (m.content.startsWith(`${prefix}remind`) || m.content.includes(`${this.client.user.id}> remind`)) {
      cleanup();
      return collector.stop();
    }
    if (m.content.toLowerCase().includes('cancel') || m.content.toLowerCase() === 'c') {
      this.sendMessage(msg.channel.id, 'Cancelled.');
      return collector.stop();
    }

    delarray.push(m.id);

    if (step === 1) {
      reminder.reminder = m.content || m.attachments[0].proxy_url;

      this.sendMessage(msg.channel.id, 'When would you like to be reminded? (e.g. 24 hours)')
        .then(m => delarray.push(m.id));
    }

    if (step === 2) {
      const parsedTime = this.utils.parseTime(m.content);

      if (parsedTime === 'INVALID') {
        return this.sendMessage(msg.channel.id, 'Invalid time argument. When would you like to be reminded? (e.g. `12 hours` or `next week`).')
          .then(m => delarray.push(m.id));
      }
      if (parsedTime === 'SET_FOR_PAST') {
        return this.sendMessage(msg.channel.id, 'Your reminder wasn\'t added because it was set for the past. Note that if you\'re trying to set a reminder for the same day at a specific time (e.g. `6 PM`), UTC time will be assumed. You can fix this by including your timezone (e.g. `6 PM PST`).\n\nWhen would you like to be reminded? (e.g. `12 hours` or `next week`).')
          .then(m => delarray.push(m.id));
      }

      reminder.dueDate = parsedTime.absolute;

      this.sendMessage(msg.channel.id, 'Would you like to receive the reminder in a specific channel, or in your DMs?\nMention the channel you\'d like to receive the reminder in, or send `DM` if you\'d like to receive it in your DMs.')
        .then(m => delarray.push(m.id));
    }

    if (step === 3) {
      if (!m.content.toLowerCase().startsWith('dm')) {
        if (!m.channelMentions[0] && !m.content.includes('here')) {
          return this.sendMessage(msg.channel.id, 'You need to either ping the channel you\'d like to receive your reminder in, send `here` or send `DM`.\nWhere would you like to receive your reminder?')
            .then(m => delarray.push(m.id));
        }
        reminder.channelID = m.channelMentions[0] || m.channel.id;
      }

      this.sendMessage(msg.channel.id, 'Would you like this reminder to be recurring? Send how frequently (e.g. `every hour` or `every 3 weeks`) or send `n` for no.')
        .then(m => delarray.push(m.id));
    }

    if (step === 4) {
      if (!['n', 'no'].includes(m.content.toLowerCase())) {
        reminder.recurringArg = m.content;
        const parsed = this.utils.parseTime(m.content);

        if (parsed === 'INVALID' || parsed === 'SET_FOR_PAST' || parsed.mode !== 'relative') {
          return this.sendMessage(msg.channel.id, `I was unable to recognize \`${m.content}\` as a valid recurring time argument. Please enter a proper recurring time argument, e.g. \`every 12 hours\` or \`every month\`.`);
        }

        reminder.recurring = parsed.relative;
      }

      collector.stop();
      await this.db.addReminder(reminder);

      const fields = [
        {
          name: 'Target channel',
          value: reminder.channelID ? `<#${reminder.channelID}>` : `<@${msg.author.id}>'s DMs`,
          inline: true
        }
      ];

      if (reminder.recurring) {
        fields.push({
          name: 'Recurring',
          value: `${reminder.recurringArg.trim()} (every ${this.utils.parseDuration(reminder.recurring / 1000)})`,
          inline: true
        });
      }

      this.sendMessage(msg.channel.id, {
        title: 'Reminder successfully added',
        description: reminder.reminder,
        fields: fields,
        footer: { text: 'Reminder set for ' },
        timestamp: new Date(reminder.dueDate)
      });
      cleanup();
    }
    step++;
  });

  collector.on('end', async (_, reason) => {
    if (reason === 'time') {
      this.sendMessage(msg.channel.id, 'Prompt timed out.');
    }
  });
}

module.exports = remindmeArgless;<|endoftext|>


<commit_before>'use strict';

var Task        = require('ember-cli/lib/models/task');
var Promise     = require('ember-cli/lib/ext/promise');

var cordovaPath = require('../utils/cordova-path');
var fs          = require('fs');
var path        = require('path');

module.exports = Task.extend({
  run: function(hookName) {
    var root = this.project.root;
    var hookPath = path.join(cordovaPath(this.project), 'hooks', hookName);

    if (fs.exists(hookPath)) {
      this.ui.writeLine("Located hook for: " + hookName);
      var hook = require(hookPath);
      hook();
      this.ui.writeLine("Ran hook for: " + hookName);
    }

    return Promise.resolve()
  }
});
<commit_msg>refactor(run hook): ensure file check in sync<commit_after>'use strict';

var Task        = require('ember-cli/lib/models/task');
var Promise     = require('ember-cli/lib/ext/promise');

var cordovaPath = require('../utils/cordova-path');
var fs          = require('fs');
var path        = require('path');

module.exports = Task.extend({
  run: function(hookName) {
    var root = this.project.root;
    var hookPath = path.join(cordovaPath(this.project, true), 'hooks', hookName + '.js');

    if (fs.existsSync(hookPath)) {
      this.ui.writeLine("Located hook for: " + hookName);
      var hook = require(hookPath);
      hook();
      this.ui.writeLine("Ran hook for: " + hookName);
    }

    return Promise.resolve()
  }
});
<|endoftext|>


<commit_before>// ========================================================================
// SproutCore -- JavaScript Application Framework
// Copyright ©2006-2008, Sprout Systems, Inc. and contributors.
// Portions copyright ©2008 Apple Inc.  All rights reserved.
// ========================================================================

/**
  @class

  SelectFieldView displays browser-native popup menu.  To use this view,
  you should either bake into the HTML the preset list of options, or
  you can set the -objects property to an array of items to show.  The
  value is current value of the select.

  @extends SC.FieldView
  @author Charles Jolley
  @author Mike Ball
  @since SproutCore 1.0
*/
SC.SelectFieldView = SC.FieldView.extend(
/** @scope SC.SelectFieldView.prototype */ {

  tagName: 'select',
  classNames: ['sc-select-field-view'],

  /**
    An array of items that will form the menu you want to show.
  */
  objects: [],

  /**
    Binding default for an array of objects
  */
  objectsBindingDefault: SC.Binding.multiple(),

  /**
    If you set this to a non-null value, then the name shown for each
    menu item will be pulled from the object using the named property.
    if this is null, the collection objects themselves will be used.
  */
  nameKey: null,

  /**
   If you set this to a non-null value, then the value of this key will
   be used to sort the objects.  If this is not set, then nameKey will
   be used.
  */
  sortKey: null,

  /**
     Set this to a non-null value to use a key from the passed set of objects
     as the value for the options popup.  If you don't set this, then the
     objects themselves will be used as the value.
  */
  valueKey: null,

  /**
    set this to non-null to place an empty option at the top of the menu.
  */
  emptyName: null,

  /**
    if true, the empty name will be localized.
  */
  localize: false,

  /**
    if true, it means that the nameKey, valueKey or objects changed
  */
  cpDidChange: YES,

  /**
    if true, it means that no sorting will occur, objects will appear
    in the same order as in the array
  */
  disableSort: NO,

  /**
    override this to change the enabled/disabled state of menu items as they
    are built.  Return false if you want the menu item to be disabled.

    @param itemValue the value for the item to validate
    @param itemName the name of the menu item to validate
    @returns YES if the item should be enabled, NO otherwise
  */
  validateMenuItem: function(itemValue, itemName) {
    return true ;
  },

  /**
    override this method to implement your own sorting of the menu. By
    default, menu items are sorted using the value shown or the sortKey

    @param objects the unsorted array of objects to display.
    @returns sorted array of objects
  */
  sortObjects: function(objects) {
    if(!this.get('disableSort')){
      var nameKey = this.get('sortKey') || this.get('nameKey') ;
      objects = objects.sort(function(a,b) {
        if (nameKey) {
          a = a.get ? a.get(nameKey) : a[nameKey] ;
          b = b.get ? b.get(nameKey) : b[nameKey] ;
        }
        return (a<b) ? -1 : ((a>b) ? 1 : 0) ;
      }) ;
    }
    return objects ;
  },

  render: function(context, firstTime) {
    if (this.get('cpDidChange')) {
      this.set('cpDidChange', NO);
      // get list of objects.
      var nameKey = this.get('nameKey') ;
      var valueKey = this.get('valueKey') ;
      var objects = this.get('objects') ;
      var fieldValue = this.get('value') ;
      var el, selectElement;

      // get the localization flag.
      var shouldLocalize = this.get('localize');

      // convert fieldValue to guid, if it is an object.
      if (!valueKey && fieldValue) fieldValue = SC.guidFor(fieldValue) ;
      if ((fieldValue === null) || (fieldValue === '')) fieldValue = '***' ;

      if (objects) {
        objects = this.sortObjects(objects) ; // sort'em.
        // var html = [] ;
        if(!firstTime){
          selectElement=this.$input()[0];
          selectElement.innerHTML='';
        }

        var emptyName = this.get('emptyName') ;
        if (emptyName) {
          if (shouldLocalize) emptyName = emptyName.loc() ;
          if(firstTime){
            context.push('<option value="***">'+emptyName+'</option>',
                          '<option disabled="disabled"></option>') ;
          }else{
            el=document.createElement('option');
            el.value="***";
            el.innerHTML=emptyName;
            selectElement.appendChild(el);
            el=document.createElement('option');
            el.disabled="disabled";
            selectElement.appendChild(el);
          }
        }

          // generate option elements.
        objects.forEach(function(object) {
        if (object) {
          // either get the name from the object or convert object to string.
          var name = nameKey ? (object.get ? object.get(nameKey) : object[nameKey]) : object.toString() ;

          // localize name if specified.
          if(shouldLocalize)
          {
            name = name.loc();
          }

          // get the value using the valueKey or the object if no valueKey.
          // then convert to a string or use _guid if one of available.
          var value = (valueKey) ? (object.get ? object.get(valueKey) : object[valueKey]) : object ;
          if (value) value = (SC.guidFor(value)) ? SC.guidFor(value) : value.toString() ;

          // render HTML
          var disable = (this.validateMenuItem && this.validateMenuItem(value, name)) ? '' : 'disabled="disabled" ' ;
          if(firstTime){
            context.push('<option '+disable+'value="'+value+'">'+name+'</option>') ;
          } else{
            el=document.createElement('option');
            el.value=value;
            el.innerHTML=name;
            if(disable.length>0) el.disable="disabled";
            selectElement.appendChild(el);
          }
        // null value means separator.
        } else {
          if(firstTime){
            context.push('<option disabled="disabled"></option>') ;
          }else{
            el=document.createElement('option');
            el.disabled="disabled";
            selectElement.appendChild(el);
          }
        }
      }, this );

      this.setFieldValue(fieldValue);

      } else {
        this.set('value',null);
      }
    }
  },

  displayProperties: ['objects','nameKey','valueKey'],

  _objectsObserver: function() {
    this.set('cpDidChange', YES);
  }.observes('objects'),

  _nameKeyObserver: function() {
    this.set('cpDidChange', YES);
  }.observes('nameKey'),

  _valueKeyObserver: function() {
    this.set('cpDidChange', YES);
  }.observes('valueKey'),

  // .......................................
  // PRIVATE
  //

  $input: function() { return this.$(); },

  /* @private */
  mouseDown: function(evt) {

    if (!this.get('isEnabled')) {
      evt.stop();
      return YES;
    } else return sc_super();
  },

  // when fetching the raw value, convert back to an object if needed...
  /** @private */
  getFieldValue: function() {
    var value = sc_super(); // get raw value...
    var valueKey = this.get('valueKey') ;
    var objects = this.get('objects') ;
    var found, object;

    // Handle empty selection.
    if (value == '***') {
      value = null ;

    // If no value key was set and there are objects then match back to an
    // object.
    } else if (value && objects) {
      // objects = Array.from(objects) ;

      var loc = (SC.typeOf(objects.length) === SC.T_FUNCTION) ? objects.length() : objects.length;

      found = null ; // matching object goes here.
      while(!found && (--loc >= 0)) {
        object = objects.objectAt? objects.objectAt(loc) : objects[loc] ;
        if (!object) continue; // null means placeholder; just skip

        // get value using valueKey if there is one or use object
        // map to _guid or toString.
        if (valueKey) object = (object.get) ? object.get(valueKey) : object[valueKey] ;
        var ov = (object) ? (SC.guidFor(object) ? SC.guidFor(object) : object.toString()) : null ;

        // use this object value if it matches.
        if (value == ov) found = object ;
      }
    }

    return (valueKey || found) ? found : value;
  },

  setFieldValue: function(newValue) {
    if (SC.none(newValue)) { newValue = '' ; }
    else {
      newValue = ((newValue) ? (SC.guidFor(newValue) ? SC.guidFor(newValue) : newValue.toString()) : null );
    }
    this.$input().val(newValue);
    return this ;
  },

  fieldDidFocus: function() {
    var isFocused = this.get('isFocused');
    if (!isFocused) this.set('isFocused', true);
  },

  fieldDidBlur: function() {
    var isFocused = this.get('isFocused');
    if (isFocused) this.set('isFocused', false);
  },

  _isFocusedObserver: function() {
    this.$().setClass('focus', this.get('isFocused'));
  }.observes('isFocused'),

  didCreateLayer: function() {
    var input = this.$input();
    if (this.get('isEnabled') === false) this.$()[0].disabled = true;
    SC.Event.add(input, 'blur', this, this.fieldDidBlur);
    SC.Event.add(input, 'focus',this, this.fieldDidFocus);
    return sc_super();
  },

  willDestroyLayer: function() {
    var input = this.$input();
    SC.Event.remove(input, 'focus', this, this.fieldDidFocus);
    SC.Event.remove(input, 'blur', this, this.fieldDidBlur);
    return sc_super();
  }

});
<commit_msg>Use SC.Enumerable's sortProperty to sort objects so that this works on any SC.Enumerable not just native arrays.<commit_after>// ========================================================================
// SproutCore -- JavaScript Application Framework
// Copyright ©2006-2008, Sprout Systems, Inc. and contributors.
// Portions copyright ©2008 Apple Inc.  All rights reserved.
// ========================================================================

/**
  @class

  SelectFieldView displays browser-native popup menu.  To use this view,
  you should either bake into the HTML the preset list of options, or
  you can set the -objects property to an array of items to show.  The
  value is current value of the select.

  @extends SC.FieldView
  @author Charles Jolley
  @author Mike Ball
  @since SproutCore 1.0
*/
SC.SelectFieldView = SC.FieldView.extend(
/** @scope SC.SelectFieldView.prototype */ {

  tagName: 'select',
  classNames: ['sc-select-field-view'],

  /**
    An array of items that will form the menu you want to show.
  */
  objects: [],

  /**
    Binding default for an array of objects
  */
  objectsBindingDefault: SC.Binding.multiple(),

  /**
    If you set this to a non-null value, then the name shown for each
    menu item will be pulled from the object using the named property.
    if this is null, the collection objects themselves will be used.
  */
  nameKey: null,

  /**
   If you set this to a non-null value, then the value of this key will
   be used to sort the objects.  If this is not set, then nameKey will
   be used.
  */
  sortKey: null,

  /**
     Set this to a non-null value to use a key from the passed set of objects
     as the value for the options popup.  If you don't set this, then the
     objects themselves will be used as the value.
  */
  valueKey: null,

  /**
    set this to non-null to place an empty option at the top of the menu.
  */
  emptyName: null,

  /**
    if true, the empty name will be localized.
  */
  localize: false,

  /**
    if true, it means that the nameKey, valueKey or objects changed
  */
  cpDidChange: YES,

  /**
    if true, it means that no sorting will occur, objects will appear
    in the same order as in the array
  */
  disableSort: NO,

  /**
    override this to change the enabled/disabled state of menu items as they
    are built.  Return false if you want the menu item to be disabled.

    @param itemValue the value for the item to validate
    @param itemName the name of the menu item to validate
    @returns YES if the item should be enabled, NO otherwise
  */
  validateMenuItem: function(itemValue, itemName) {
    return true ;
  },

  /**
    override this method to implement your own sorting of the menu. By
    default, menu items are sorted using the value shown or the sortKey

    @param objects the unsorted array of objects to display.
    @returns sorted array of objects
  */
  sortObjects: function(objects) {
    if(!this.get('disableSort')){
      var nameKey = this.get('sortKey') || this.get('nameKey') ;
      objects = objects.sortProperty(nameKey);
    }
    return objects ;
  },

  render: function(context, firstTime) {
    if (this.get('cpDidChange')) {
      this.set('cpDidChange', NO);
      // get list of objects.
      var nameKey = this.get('nameKey') ;
      var valueKey = this.get('valueKey') ;
      var objects = this.get('objects') ;
      var fieldValue = this.get('value') ;
      var el, selectElement;

      // get the localization flag.
      var shouldLocalize = this.get('localize');

      // convert fieldValue to guid, if it is an object.
      if (!valueKey && fieldValue) fieldValue = SC.guidFor(fieldValue) ;
      if ((fieldValue === null) || (fieldValue === '')) fieldValue = '***' ;

      if (objects) {
        objects = this.sortObjects(objects) ; // sort'em.
        // var html = [] ;
        if(!firstTime){
          selectElement=this.$input()[0];
          selectElement.innerHTML='';
        }

        var emptyName = this.get('emptyName') ;
        if (emptyName) {
          if (shouldLocalize) emptyName = emptyName.loc() ;
          if(firstTime){
            context.push('<option value="***">'+emptyName+'</option>',
                          '<option disabled="disabled"></option>') ;
          }else{
            el=document.createElement('option');
            el.value="***";
            el.innerHTML=emptyName;
            selectElement.appendChild(el);
            el=document.createElement('option');
            el.disabled="disabled";
            selectElement.appendChild(el);
          }
        }

          // generate option elements.
        objects.forEach(function(object) {
        if (object) {
          // either get the name from the object or convert object to string.
          var name = nameKey ? (object.get ? object.get(nameKey) : object[nameKey]) : object.toString() ;

          // localize name if specified.
          if(shouldLocalize)
          {
            name = name.loc();
          }

          // get the value using the valueKey or the object if no valueKey.
          // then convert to a string or use _guid if one of available.
          var value = (valueKey) ? (object.get ? object.get(valueKey) : object[valueKey]) : object ;
          if (value) value = (SC.guidFor(value)) ? SC.guidFor(value) : value.toString() ;

          // render HTML
          var disable = (this.validateMenuItem && this.validateMenuItem(value, name)) ? '' : 'disabled="disabled" ' ;
          if(firstTime){
            context.push('<option '+disable+'value="'+value+'">'+name+'</option>') ;
          } else{
            el=document.createElement('option');
            el.value=value;
            el.innerHTML=name;
            if(disable.length>0) el.disable="disabled";
            selectElement.appendChild(el);
          }
        // null value means separator.
        } else {
          if(firstTime){
            context.push('<option disabled="disabled"></option>') ;
          }else{
            el=document.createElement('option');
            el.disabled="disabled";
            selectElement.appendChild(el);
          }
        }
      }, this );

      this.setFieldValue(fieldValue);

      } else {
        this.set('value',null);
      }
    }
  },

  displayProperties: ['objects','nameKey','valueKey'],

  _objectsObserver: function() {
    this.set('cpDidChange', YES);
  }.observes('objects'),

  _nameKeyObserver: function() {
    this.set('cpDidChange', YES);
  }.observes('nameKey'),

  _valueKeyObserver: function() {
    this.set('cpDidChange', YES);
  }.observes('valueKey'),

  // .......................................
  // PRIVATE
  //

  $input: function() { return this.$(); },

  /* @private */
  mouseDown: function(evt) {

    if (!this.get('isEnabled')) {
      evt.stop();
      return YES;
    } else return sc_super();
  },

  // when fetching the raw value, convert back to an object if needed...
  /** @private */
  getFieldValue: function() {
    var value = sc_super(); // get raw value...
    var valueKey = this.get('valueKey') ;
    var objects = this.get('objects') ;
    var found, object;

    // Handle empty selection.
    if (value == '***') {
      value = null ;

    // If no value key was set and there are objects then match back to an
    // object.
    } else if (value && objects) {
      // objects = Array.from(objects) ;

      var loc = (SC.typeOf(objects.length) === SC.T_FUNCTION) ? objects.length() : objects.length;

      found = null ; // matching object goes here.
      while(!found && (--loc >= 0)) {
        object = objects.objectAt? objects.objectAt(loc) : objects[loc] ;
        if (!object) continue; // null means placeholder; just skip

        // get value using valueKey if there is one or use object
        // map to _guid or toString.
        if (valueKey) object = (object.get) ? object.get(valueKey) : object[valueKey] ;
        var ov = (object) ? (SC.guidFor(object) ? SC.guidFor(object) : object.toString()) : null ;

        // use this object value if it matches.
        if (value == ov) found = object ;
      }
    }

    return (valueKey || found) ? found : value;
  },

  setFieldValue: function(newValue) {
    if (SC.none(newValue)) { newValue = '' ; }
    else {
      newValue = ((newValue) ? (SC.guidFor(newValue) ? SC.guidFor(newValue) : newValue.toString()) : null );
    }
    this.$input().val(newValue);
    return this ;
  },

  fieldDidFocus: function() {
    var isFocused = this.get('isFocused');
    if (!isFocused) this.set('isFocused', true);
  },

  fieldDidBlur: function() {
    var isFocused = this.get('isFocused');
    if (isFocused) this.set('isFocused', false);
  },

  _isFocusedObserver: function() {
    this.$().setClass('focus', this.get('isFocused'));
  }.observes('isFocused'),

  didCreateLayer: function() {
    var input = this.$input();
    if (this.get('isEnabled') === false) this.$()[0].disabled = true;
    SC.Event.add(input, 'blur', this, this.fieldDidBlur);
    SC.Event.add(input, 'focus',this, this.fieldDidFocus);
    return sc_super();
  },

  willDestroyLayer: function() {
    var input = this.$input();
    SC.Event.remove(input, 'focus', this, this.fieldDidFocus);
    SC.Event.remove(input, 'blur', this, this.fieldDidBlur);
    return sc_super();
  }

});
<|endoftext|>


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

  module('assert', function () {
    var assert = {};
    var fail;

    assert.clear = function () {
      if (assert.error) {
        delete assert.error;
      }
    };

    assert.equal = function (actual, expected) {
      if (actual !== expected) {
        fail(actual + ' is not equal to ' + expected);
      }
    };

    assert.throws = function (fn, comparer) {
      try {
        if (!isFunction(fn)) {
          fail('fn is not a function');
        } else {
          fn();
          fail('function did not throw an error');
        }
      } catch (err) {
        if (isFunction(comparer) && !comparer(err)) {
          fail('comparer function did not return true');
        }
      }
    };

    assert.true = function (value) {
      if (typeof value !== 'boolean' || !value) {
        fail('value is not true');
      }
    };

    fail = function (message) {
      assert.error = new Error(message);
    };

    module.exports = assert;
  });
}());
<commit_msg>Fixed missing isFunction utility function<commit_after>(function () {
  'use strict';

  module('assert', function () {
    var isFunction = require('utils').isFunction;
    var assert = {};
    var fail;

    assert.clear = function () {
      if (assert.error) {
        delete assert.error;
      }
    };

    assert.equal = function (actual, expected) {
      if (actual !== expected) {
        fail(actual + ' is not equal to ' + expected);
      }
    };

    assert.throws = function (fn, comparer) {
      try {
        if (!isFunction(fn)) {
          fail('fn is not a function');
        } else {
          fn();
          fail('function did not throw an error');
        }
      } catch (err) {
        if (isFunction(comparer) && !comparer(err)) {
          fail('comparer function did not return true');
        }
      }
    };

    assert.true = function (value) {
      if (typeof value !== 'boolean' || !value) {
        fail('value is not true');
      }
    };

    fail = function (message) {
      assert.error = new Error(message);
    };

    module.exports = assert;
  });
}());
<|endoftext|>


<commit_before>var sys = require('sys');
var http = require('http');
var fs = require('fs');

var redis = require('redis').saveClient;
var tempalias = require('tempalias');
var config = require('config');
var paperboy = require('paperboy');

var p = tempalias.AliasProvider;

fs.realpath('lib/../public', function(err, public_root){
  http.createServer(function(req, res) {

    /* Support for google's crawlable ajax specification.

       Note that this isn't quite correct in that it returns the content
       without the framing, but as that fragment always contains all the links,
       what google sees in this case is just the css less pure fragments, but
       *containing all the content*.
     */
    var url = require('url').parse(req.url, true);
    if (url.query && url.query._escaped_fragment_){
      req.url = '/templates/'+url.query._escaped_fragment_+'.html';
    }
    if (!url.query) url.query = {};

    if (url.pathname == '/aliases'){

      var headers = {
        "Content-Type": url.query.callback ? "text/javascript" : "application/json",
        'Date': (new Date()).toUTCString()
      };

      var sendAlias = function(alias){
        var body = JSON.stringify(alias);
        if (url.query.callback)
          body = url.query.callback + '(' + body + ')';
        headers['Content-Length'] = body.length;
        res.writeHead(200, headers);
        res.end(body);
      };

      var err = function(code, resp){
        var body = JSON.stringify(resp);
        if (url.query.callback)
          body = url.query.callback + '(' + body + ')';
        headers['Content-Length'] = body.length;
        res.writeHead(code, headers);
        res.end(body);
      };

      // too bad SETNX counts as a write operation even when it doesn't write.
      // that's why I can't just use redis' EXPIRE command
      var lock_key = 'lock:'+req.socket.remoteAddress;
      var t = (new Date()).getTime();
      redis.setnx(lock_key, t+30000, function(lr){
        if (!lr){
          redis.get(lock_key, function(exp){
            if (parseInt(exp, 10) < (t)){
              redis.del(lock_key);
            }else{
              err(403, {error: 'rate-limited', description: 'please wait a moment before generating the next alias'});
            }
          });
        }
      });

      process.addListener('uncaughtException', function (e) {
        var msg = (e && e.message) ?  e.message : 'unknown';
        err(500, {error: 'server-error', description: msg});
      });

      var genAlias = function(data){
        var alias = p.getNew();
        try{
          alias.setInfo(data);
        }catch(e){
          err(400, {
            error: "invalid-data",
            description: e.message
          });
        }
        try{
          p.save(alias, function(id){
            try{
              alias.currentDate = new Date();
              var f = alias.valid_from ? alias.valid_from.getDate() : new Date();
              if (alias.valid_until && !alias.valid_from){
                alias.days = Math.ceil((alias.valid_until.getTime()-f.getTime())/(1000*60*60*24));
              }
              sendAlias(alias);
            }catch(e){
              err(500, {error: "server-exception", description: e.message});
            }
          });
        }catch(e){
          err(500, {error: "server-exception", description: e.message});
        }
      };

      if (!url.query.callback){
        if (req.method != 'POST'){
          err(405, {
            error: "method-not-allowed",
            description: '/aliases only takes POST'
          });
          return;
        }
        if (req.headers['content-type'].split(';')[0] != 'application/json'){
          err(400, {
            error: "invalid-request-type",
            description: "invalid request type. Need application/json, but got "+req.headers['content-type']
          });
          return;
        }
        var len = req.headers['content-length'] || 1024;
        if (!url.query.callback && len >= 1024){
          err(400 , {
            error: "invalid-content-length",
            description: "no or too big content length provided"
          });
        }
        var reqbody = '';
        var error = false;
        req.addListener('data', function(chunk){
          reqbody += chunk;
          if (reqbody.length >= 1024){
            err = true;
            err(400, { error: "too-much-data", description: "request too big"});
          }
        });
        req.addListener('end', function(){
          genAlias(JSON.parse(reqbody));
        });
        return;
      }else{
        if(req.method != 'GET'){
          err(400, {
            error: "method-not-allowed",
            description: 'with callback only GET allowed'
          });
          return;
        }
        genAlias(url.query);
      }
      return; // don't pass to paperboy
    }

    // other cases: Divert to paperboy
    paperboy
        .deliver(public_root, req, res)
        .addHeader('Date', (new Date()).toUTCString())
        .error(function(statCode,msg) {
          res.writeHead(statCode, {'Content-Type': 'text/plain'});
          res.write("Error: " + statCode + ': ' + msg);
          res.close();
        })
        .otherwise(function(err) {
          var statCode = 404;
          res.writeHead(statCode, {'Content-Type': 'text/plain'});
          res.end('not found');
        });
  }).listen(config.http.port, config.http.listen);
  sys.puts('tempalias HTTP daemon running on port ' + config.http.port +
    (config.http.listen ? ' on interface ' + config.http.listen : " on all interfaces") );
});
<commit_msg>return 200 even on errors in jsonp-mode<commit_after>var sys = require('sys');
var http = require('http');
var fs = require('fs');

var redis = require('redis').saveClient;
var tempalias = require('tempalias');
var config = require('config');
var paperboy = require('paperboy');

var p = tempalias.AliasProvider;

fs.realpath('lib/../public', function(err, public_root){
  http.createServer(function(req, res) {

    /* Support for google's crawlable ajax specification.

       Note that this isn't quite correct in that it returns the content
       without the framing, but as that fragment always contains all the links,
       what google sees in this case is just the css less pure fragments, but
       *containing all the content*.
     */
    var url = require('url').parse(req.url, true);
    if (url.query && url.query._escaped_fragment_){
      req.url = '/templates/'+url.query._escaped_fragment_+'.html';
    }
    if (!url.query) url.query = {};

    if (url.pathname == '/aliases'){

      var headers = {
        "Content-Type": url.query.callback ? "text/javascript" : "application/json",
        'Date': (new Date()).toUTCString()
      };

      var sendAlias = function(alias){
        var body = JSON.stringify(alias);
        if (url.query.callback)
          body = url.query.callback + '(' + body + ')';
        headers['Content-Length'] = body.length;
        res.writeHead(200, headers);
        res.end(body);
      };

      var err = function(code, resp){
        var body = JSON.stringify(resp);
        if (url.query.callback){
          body = url.query.callback + '(' + body + ')';
          // JSONp can't cope with non-200-responses
          code = 200;
        }
        headers['Content-Length'] = body.length;
        res.writeHead(code, headers);
        res.end(body);
      };

      // too bad SETNX counts as a write operation even when it doesn't write.
      // that's why I can't just use redis' EXPIRE command
      var lock_key = 'lock:'+req.socket.remoteAddress;
      var t = (new Date()).getTime();
      redis.setnx(lock_key, t+30000, function(lr){
        if (!lr){
          redis.get(lock_key, function(exp){
            if (parseInt(exp, 10) < (t)){
              redis.del(lock_key);
            }else{
              err(403, {error: 'rate-limited', description: 'please wait a moment before generating the next alias'});
            }
          });
        }
      });

      process.addListener('uncaughtException', function (e) {
        var msg = (e && e.message) ?  e.message : 'unknown';
        err(500, {error: 'server-error', description: msg});
      });

      var genAlias = function(data){
        var alias = p.getNew();
        try{
          alias.setInfo(data);
        }catch(e){
          err(400, {
            error: "invalid-data",
            description: e.message
          });
        }
        try{
          p.save(alias, function(id){
            try{
              alias.currentDate = new Date();
              var f = alias.valid_from ? alias.valid_from.getDate() : new Date();
              if (alias.valid_until && !alias.valid_from){
                alias.days = Math.ceil((alias.valid_until.getTime()-f.getTime())/(1000*60*60*24));
              }
              sendAlias(alias);
            }catch(e){
              err(500, {error: "server-exception", description: e.message});
            }
          });
        }catch(e){
          err(500, {error: "server-exception", description: e.message});
        }
      };

      if (!url.query.callback){
        if (req.method != 'POST'){
          err(405, {
            error: "method-not-allowed",
            description: '/aliases only takes POST'
          });
          return;
        }
        if (req.headers['content-type'].split(';')[0] != 'application/json'){
          err(400, {
            error: "invalid-request-type",
            description: "invalid request type. Need application/json, but got "+req.headers['content-type']
          });
          return;
        }
        var len = req.headers['content-length'] || 1024;
        if (!url.query.callback && len >= 1024){
          err(400 , {
            error: "invalid-content-length",
            description: "no or too big content length provided"
          });
        }
        var reqbody = '';
        var error = false;
        req.addListener('data', function(chunk){
          reqbody += chunk;
          if (reqbody.length >= 1024){
            err = true;
            err(400, { error: "too-much-data", description: "request too big"});
          }
        });
        req.addListener('end', function(){
          genAlias(JSON.parse(reqbody));
        });
        return;
      }else{
        if(req.method != 'GET'){
          err(400, {
            error: "method-not-allowed",
            description: 'with callback only GET allowed'
          });
          return;
        }
        genAlias(url.query);
      }
      return; // don't pass to paperboy
    }

    // other cases: Divert to paperboy
    paperboy
        .deliver(public_root, req, res)
        .addHeader('Date', (new Date()).toUTCString())
        .error(function(statCode,msg) {
          res.writeHead(statCode, {'Content-Type': 'text/plain'});
          res.write("Error: " + statCode + ': ' + msg);
          res.close();
        })
        .otherwise(function(err) {
          var statCode = 404;
          res.writeHead(statCode, {'Content-Type': 'text/plain'});
          res.end('not found');
        });
  }).listen(config.http.port, config.http.listen);
  sys.puts('tempalias HTTP daemon running on port ' + config.http.port +
    (config.http.listen ? ' on interface ' + config.http.listen : " on all interfaces") );
});
<|endoftext|>


<commit_before>/**
 * Mailvelope - secure email with OpenPGP encryption for Webmail
 * Copyright (C) 2012  Thomas Oberndörfer
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
// clean slate
var ss = require("simple-storage");
for (var obj in ss.storage) {
  console.log('delete ss:', obj);
  delete ss.storage[obj];
}
*/

var data = require('sdk/self').data;
var controller = require('data/common/lib/controller');
var pageMod = require("sdk/page-mod");
var tabs = require('sdk/tabs');

var activePageMod;
// recipients of encrypted mail
var eRecipientBuffer = {};
var scannedHosts = [];

var mailvelopePanel = require('sdk/panel').Panel({
  width: 200,
  height: 164,
  contentURL: data.url('common/ui/popup.html'),
  onMessage: onPanelMessage
});

require('sdk/widget').Widget({
  label: 'Mailvelope Options',
  id: 'mailvelope-options',
  contentURL: data.url('common/img/cryptography-icon16.png'),
  panel: mailvelopePanel
});

function init() {
  //console.log('main.js init()');
  controller.extend({initScriptInjection: initScriptInjection});
  initScriptInjection();
  injectMessageAdapter();
}

init();

function onPanelMessage(msg) {
  console.log('onPanelMessage', msg.action);
  controller.onBrowserAction(msg.action);
  mailvelopePanel.hide();
}

function initScriptInjection() {

  var filterURL = controller.getWatchListFilterURLs();

  var modOptions = {
    include: filterURL,
    onAttach: onCsAttach,
    contentScriptFile: [
      data.url('ui/messageAdapter.js'),
      data.url('common/ui/inline/build/cs-mailvelope.js')
    ],
    contentStyle: getDynamicStyle(),
    contentScriptOptions: {
      expose_messaging: false,
      data_path: data.url()
    }
  }

  if (activePageMod !== undefined) {
    activePageMod.destroy();
  }

  console.log('modOptions.include', modOptions.include);
  activePageMod = pageMod.PageMod(modOptions);

}

function onCsAttach(worker) {
  console.log("Attaching content scripts", worker.url);
  worker.port.on('port-message', controller.handlePortMessage);
  worker.port.on('connect', function(portName) {
    var eventName = 'port-message' + '.' + portName;
    var that = this;
    var port = {
      name: portName,
      postMessage: function(message) {
        that.emit(eventName, message);
      },
      ref: that
    }
    controller.addPort(port);
  });
  worker.port.on('disconnect', function(portName) {
    controller.removePort({name: portName});
  });
  worker.on('detach', function() {
    controller.removePortByRef(this);
  });
  worker.port.on('message-event', function(msg) {
    var that = this;
    controller.handleMessageEvent(msg, null, function(respData) {
      that.emit(msg.response, respData);
    });
  });
}

function getDynamicStyle() {
  var css = data.load('common/ui/inline/framestyles.css');
  var token = /\.\.\/\.\./g;
  css = css.replace(token, data.url('common'));
  return css;
}

function injectMessageAdapter() {

  pageMod.PageMod({
    include: [
      data.url('common/ui/modal/decryptPopup.html*'),
      data.url('common/ui/modal/editor.html*'),
      data.url('common/ui/inline/dialogs/encryptDialog.html*'),
      data.url('common/ui/modal/pwdDialog.html*')
    ],
    onAttach: onCsAttach,
    contentScriptFile: data.url('ui/messageAdapter.js'),
    contentScriptWhen: 'start',
    contentScriptOptions: {
      expose_messaging: true,
      data_path: data.url()
    }
  });

}
<commit_msg>Fix require path<commit_after>/**
 * Mailvelope - secure email with OpenPGP encryption for Webmail
 * Copyright (C) 2012  Thomas Oberndörfer
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
// clean slate
var ss = require("sdk/simple-storage");
for (var obj in ss.storage) {
  console.log('delete ss:', obj);
  delete ss.storage[obj];
}
*/

var data = require('sdk/self').data;
var controller = require('data/common/lib/controller');
var pageMod = require("sdk/page-mod");
var tabs = require('sdk/tabs');

var activePageMod;
// recipients of encrypted mail
var eRecipientBuffer = {};
var scannedHosts = [];

var mailvelopePanel = require('sdk/panel').Panel({
  width: 200,
  height: 164,
  contentURL: data.url('common/ui/popup.html'),
  onMessage: onPanelMessage
});

require('sdk/widget').Widget({
  label: 'Mailvelope Options',
  id: 'mailvelope-options',
  contentURL: data.url('common/img/cryptography-icon16.png'),
  panel: mailvelopePanel
});

function init() {
  //console.log('main.js init()');
  controller.extend({initScriptInjection: initScriptInjection});
  initScriptInjection();
  injectMessageAdapter();
}

init();

function onPanelMessage(msg) {
  console.log('onPanelMessage', msg.action);
  controller.onBrowserAction(msg.action);
  mailvelopePanel.hide();
}

function initScriptInjection() {

  var filterURL = controller.getWatchListFilterURLs();

  var modOptions = {
    include: filterURL,
    onAttach: onCsAttach,
    contentScriptFile: [
      data.url('ui/messageAdapter.js'),
      data.url('common/ui/inline/build/cs-mailvelope.js')
    ],
    contentStyle: getDynamicStyle(),
    contentScriptOptions: {
      expose_messaging: false,
      data_path: data.url()
    }
  }

  if (activePageMod !== undefined) {
    activePageMod.destroy();
  }

  console.log('modOptions.include', modOptions.include);
  activePageMod = pageMod.PageMod(modOptions);

}

function onCsAttach(worker) {
  console.log("Attaching content scripts", worker.url);
  worker.port.on('port-message', controller.handlePortMessage);
  worker.port.on('connect', function(portName) {
    var eventName = 'port-message' + '.' + portName;
    var that = this;
    var port = {
      name: portName,
      postMessage: function(message) {
        that.emit(eventName, message);
      },
      ref: that
    }
    controller.addPort(port);
  });
  worker.port.on('disconnect', function(portName) {
    controller.removePort({name: portName});
  });
  worker.on('detach', function() {
    controller.removePortByRef(this);
  });
  worker.port.on('message-event', function(msg) {
    var that = this;
    controller.handleMessageEvent(msg, null, function(respData) {
      that.emit(msg.response, respData);
    });
  });
}

function getDynamicStyle() {
  var css = data.load('common/ui/inline/framestyles.css');
  var token = /\.\.\/\.\./g;
  css = css.replace(token, data.url('common'));
  return css;
}

function injectMessageAdapter() {

  pageMod.PageMod({
    include: [
      data.url('common/ui/modal/decryptPopup.html*'),
      data.url('common/ui/modal/editor.html*'),
      data.url('common/ui/inline/dialogs/encryptDialog.html*'),
      data.url('common/ui/modal/pwdDialog.html*')
    ],
    onAttach: onCsAttach,
    contentScriptFile: data.url('ui/messageAdapter.js'),
    contentScriptWhen: 'start',
    contentScriptOptions: {
      expose_messaging: true,
      data_path: data.url()
    }
  });

}
<|endoftext|>


<commit_before>/* global describe, angular, beforeEach, it, waitsFor, dump, expect, runs, console */

(function (jasmine, Backbone) {
	'use strict';

	var user = 'tester',
		pass = 'foobar',
		testboxname = 'boxtest' + (new Date()).getTime(); // FIXME can't have dash in name?

	console.log('**** RUNNING TESTS (u: ' + user + ', p: ' + pass + ') ****');

	describe('indx-core store', function() {
		var injector = angular.injector(['ng', 'indx']),
			indx = injector.get('client'),
			u = injector.get('utils'),
			store1 = new indx.Store({ server_host: 'localhost:8211' }),
			store2 = new indx.Store({ server_host: 'localhost:8211' });

		it('is a Backbone Model', function () {
			expect(store1 instanceof Backbone.Model).toBe(true);
		});

		it('should be logged out', function () {

		});

		it('should fail to be logged in with invalid credentials', function () {
			var loggedin;
			store1.login(user, pass + 'aaa') // invalidate the password
				.fail(function () { loggedin = false; });
			waitsFor(function() { return loggedin === false; }, 'the user to not be logged in', 500);
			runs(function () { expect(loggedin).toBe(false); });
		});

		it('should be logged out', function () {

		});

		// login as you
		it('should successfully be logged in with valid credentials', function () {
			var loggedin;
			store1.login(user, pass).then(function () { loggedin = true; });
			waitsFor(function() { return loggedin; }, 'the user to be logged in', 500);
			runs(function () { expect(loggedin).toBe(true); });
		});

		it('should be logged in', function () {

		});

		// log out, make sure yo'ure not logged in
		it('should able to be logged out', function () {
			var loggedout;
			store1.logout().then(function () { loggedout = true; });
			waitsFor(function() { return loggedout; }, 'the user to be logged out', 500);
			runs(function () { expect(loggedout).toBe(true); });
		});

		it('should be logged out', function () {

		});

		// login as you
		it('should successfully be logged in with valid credentials', function () {
			var loggedin;
			store1.login(user, pass).then(function () { loggedin = true; });
			waitsFor(function() { return loggedin; }, 'the user to be logged in', 500);
			runs(function () { expect(loggedin).toBe(true); });
		});

		// make sure you're logged in
		it('should be logged in', function () {

		});

		it('should have a collection of boxes', function () {
			expect(store1.get('boxes')).toBeDefined();
			expect(store1.get('boxes')).toBe(store1.boxes());
			expect(store2.get('boxes')).toBeDefined();
			expect(store2.get('boxes')).toBe(store2.boxes());
		});

		describe('box collection', function () {
			it('should be empty', function () {
				expect(store1.boxes().length).toBe(0);
			});
			it('should be a Backbone Collection', function () {
				expect(store1.boxes() instanceof Backbone.Collection).toBe(true);
			});
		});

		// create box
		it('should allow a box to be created', function () {
			var box;
			store1.create_box(testboxname).then(function () {
				console.log("CREATED")
				box = store1.get_box(testboxname);
			});
			waitsFor(function () { return box; }, 'the box to be created', 1500);
			runs(function () { expect(box).toBeDefined(); });
		});

		describe('box collection', function () {
			it('should have the new box in the box collection', function () {
				expect(store1.boxes().get(testboxname)).toBeDefined();
			})
			it('should have only one box in the box collection', function () {
				expect(store1.boxes().length).toBe(1);
			});
		});

		it('should be able to create 10,000 boxes')

		describe('box collection', function () {
			it('should have 10,000 box in the box collection')
		});

		it('should be able to delete those boxes')

		it('should fail to create a box if it already exists', function () {
			var failed;
			store1.create_box(testboxname).fail(function () {
				failed = true;
			});
			waitsFor(function () { return failed; }, 'the box to not have been created', 500);
			runs(function () { expect(failed).toBe(true); });
		});

		it('should have this box within another store (should auto-update)', function () {
			waitsFor(function () { return store2.boxes().get(testboxname); }, 'another store to list the new box', 1000);
			runs(function () { expect(store2.boxes().get(testboxname)).toBeDefined(); });
		});

		// hack
		//testboxname = 'blah';

		describe('box', function () {
			var s1box, s2box;
			it('should be defined', function () {
				var b = store1.get_box(testboxname);
				expect(b).toBeDefined();
			});

			it('should be a Backbone Model')

			it('should have a cache of objects')

			describe('Object Cache', function () {
				it('should be a Backbone Collection')
			})

			it('should have a list of objects')

			describe('Object List', function () {
				it('should be an array')
			});

			it('should have a collection of files')

			describe('File Collection', function () {
				it('should be a Backbone Collection')
			})

			// making it sure it exists
			it('should be retreivable', function () {
				store1.get_box(testboxname).then(function (b) { s1box = b; });
				store2.get_box(testboxname).then(function (b) { s2box = b; });
				waitsFor(function () { return s1box && s2box; }, 'the box to be fetched', 500);
				runs(function () {
					expect(s1box).toBeDefined();
					expect(s2box).toBeDefined();
				});
			});

			it('should allow an object to be created', function () {
				var obj;
				s1box.get_obj('test1').then(function(o) { obj = o; });
				waitsFor(function () { return obj; }, 'the object to be created', 500);
				runs(function () { expect(obj).toBeDefined(); });
			});

			/*it('should not allow an object to be created if it already exists', function () {
				var obj;
				s1box.get_obj('test1').then(function(o) { obj = o; });
				waitsFor(function () { return obj; });
				runs(function () { expect(obj).toBeDefined(); });
			});*/

			describe('object', function () {
				var s1obj, s2obj;
				it('should allow the object to be fetched', function () {
					s1box.get_obj('test1').then(function (o) { s1obj = o; });
					waitsFor(function () { return s1obj; }, 'the object to be fetched', 500);
					runs(function () {
						expect(s1obj).toBeDefined();
					});
				});

				it('should allow the object to be created', function () {
					var saved;
					s1obj.save({ value: 99 }).then(function () { saved = true; });
					waitsFor(function () { return saved; }, 'the object to have changed', 500);
					runs(function () { expect(s1obj.get('value')[0]).toBe(99); });
				});
				it('should allow another store (store 2) to load the object', function () {
					s2box.get_obj('test1').then(function (o) { s2obj = o; });
					waitsFor(function () { return s2obj; }, 'the object to be fetched', 500);
					runs(function () { expect(s2obj).toBeDefined(); });
				});
				it('should be up-to-date in store 2', function () {
					waitsFor(function () { return s2obj.get('value') && s2obj.get('value')[0] === 99; },
							'the object to be up-to-date', 500);
					runs(function () { expect(s2obj.get('value')[0]).toBe(99); });
				});
				it('should not be using the same cache between stores', function () {
					expect(s1obj.attributes).not.toBe(s2obj.attributes);
				});
				it('should allow store 2 to edit the object', function () {
					var saved;
					s2obj.save({ value: 97 }).then(function () { saved = true; });
					waitsFor(function () { return saved; }, 'the object to have changed', 500);
					runs(function () { expect(s2obj.get('value')[0]).toBe(97); });
				});
				it('should have updated the object in store 1', function () {
					waitsFor(function () { return s1obj.get('value') && s1obj.get('value')[0] === 97; },
								'the object to be up-to-date', 500);
					runs(function () { expect(s1obj.get('value')[0]).toBe(97); });
				});

				it('should not allow two conflicting objects', function () {
					var s1obj, s2obj,
						passes = 0,
						fails = 0;
					s1box.get_obj('test2').then(function (o) { s1obj = o; });
					s2box.get_obj('test2').then(function (o) { s2obj = o; });
					s1box.save().then(function () { passes++; }).fail(function () { fails++; });
					s2box.save().then(function () { passes++; }).fail(function () { fails++; });
					waitsFor(function () { return passes + fails === 2; }, 'the boxes to have changed', 500);
					runs(function () {
						expect(passes).toBe(1);
						expect(fails).not.toBe(0);
					});
				});
			});

			it('should allow a file to be created')

			describe('file', function () {
				it('should allow the file to be fetched')

			})

			it('should be deletable', function () {
				var destroyed;
				s1box.destroy().then(function () { destroyed = true; });
				waitsFor(function () { return destroyed; }, 'the box to be deleted', 500);
				runs(function () { expect(s1box).not.toBeDefined(); });
			});
		});

		// create new object that didnt exist before, check to make sure it got created
		// ?? create new object that existed before, check to see if error // updates object
		// update object, make sure it propagate
		// coordinated testing: Can we ever do this??
		//   write an object, waitFor the thing to propagate to the other client
		// delete object, make sure it's dead, jim

		// it('getinfo', function() {
		// 	var gi;
		// 	runs(function() {
		// 		store.getInfo()
		// 			.then(function(x) { dump('getinfo ', x); gi = x; })
		// 			.fail(function(x) { console.error('fail logging in ', x); });
		// 	});
		// 	waitsFor(function() { return gi; });
		// 	runs(function() {
		// 		expect(gi).toBeDefined();
		// 		dump('done waiting ', gi);
		// 	});
		// });
		// it('should fetch boxes', function() {
		// 	var boxes;
		// 	runs(function() {
		// 		store.fetch()
		// 			.then(function(x) { dump('boxes ', x); boxes = store.boxes(); })
		// 			.fail(function(x) { console.error('fail logging in ', x); });
		// 	});
		// 	waitsFor(function() { return boxes; });
		// 	runs(function() {
		// 		dump('boxes >> ', boxes.map(function(x) { return x.get_id(); }));
		// 	});
		// });

	});

}(this.jasmine, Backbone));
<commit_msg>Some stress testing of box creation<commit_after>/* global describe, angular, beforeEach, it, waitsFor, dump, expect, runs, console */

(function (jasmine, $, _, Backbone) {
	'use strict';

	var user = 'tester',
		pass = 'foobar',
		boxcreations = 3;

	console.log('**** RUNNING TESTS (u: ' + user + ', p: ' + pass + ') ****');

	var testboxname = 'boxtest' + (new Date()).getTime() + 'r' + Math.round(Math.random() * 10000); // FIXME can't have dash in name?
console.log(testboxname)
	describe('indx-core store', function() {
		var injector = angular.injector(['ng', 'indx']),
			indx = injector.get('client'),
			u = injector.get('utils'),
			store1 = new indx.Store({ server_host: 'localhost:8211' }),
			store2 = new indx.Store({ server_host: 'localhost:8211' });

		it('is a Backbone Model', function () {
			expect(store1 instanceof Backbone.Model).toBe(true);
		});

		it('should be logged out', function () {

		});

		it('should fail to be logged in with invalid credentials', function () {
			var loggedin;
			store1.login(user, pass + 'aaa') // invalidate the password
				.fail(function () { loggedin = false; });
			waitsFor(function() { return loggedin === false; }, 'the user to not be logged in', 500);
			runs(function () { expect(loggedin).toBe(false); });
		});

		it('should be logged out', function () {

		});

		// login as you
		it('should successfully be logged in with valid credentials', function () {
			var loggedin;
			store1.login(user, pass).then(function () { loggedin = true; });
			waitsFor(function() { return loggedin; }, 'the user to be logged in', 500);
			runs(function () { expect(loggedin).toBe(true); });
		});

		it('should be logged in', function () {

		});

		// log out, make sure yo'ure not logged in
		it('should able to be logged out', function () {
			var loggedout;
			store1.logout().then(function () { loggedout = true; });
			waitsFor(function() { return loggedout; }, 'the user to be logged out', 500);
			runs(function () { expect(loggedout).toBe(true); });
		});

		it('should be logged out', function () {

		});

		// login as you
		it('should successfully be logged in with valid credentials', function () {
			var loggedin;
			store1.login(user, pass).then(function () { loggedin = true; });
			waitsFor(function() { return loggedin; }, 'the user to be logged in', 500);
			runs(function () { expect(loggedin).toBe(true); });
		});

		// make sure you're logged in
		it('should be logged in', function () {

		});

		it('should have a collection of boxes', function () {
			expect(store1.get('boxes')).toBeDefined();
			expect(store1.get('boxes')).toBe(store1.boxes());
			expect(store2.get('boxes')).toBeDefined();
			expect(store2.get('boxes')).toBe(store2.boxes());
		});

		describe('box collection', function () {
			it('should be empty', function () {
				expect(store1.boxes().length).toBe(0);
			});
			it('should be a Backbone Collection', function () {
				expect(store1.boxes() instanceof Backbone.Collection).toBe(true);
			});
		});

		// create box
		it('should allow a box to be created', function () {
			var box;
			store1.create_box(testboxname).then(function () {
				box = store1.get_box(testboxname);
			});
			waitsFor(function () { return box; }, 'the box to be created', 1500);
			runs(function () { expect(box).toBeDefined(); });
		});

		describe('box collection', function () {
			it('should have the new box in the box collection', function () {
				expect(store1.boxes().get(testboxname)).toBeDefined();
			})
			it('should have only one box in the box collection', function () {
				expect(store1.boxes().length).toBe(1);
			});
		});

		var tmpBoxes = {},
			tmpBoxesDfds = [];
		it('should be able to create ' + boxcreations + ' boxes', function () {
			var created;

			_.times(boxcreations, function (i) {
				var boxname = testboxname + 'tmp' + i,
					$dfd = $.Deferred();

				tmpBoxesDfds = $dfd;

				store1.create_box(boxname).then(function () {
					$dfd.resolve();
					tmpBoxes[boxname] = store1.get_box(testboxname);
				});
			});

			$.when.apply(null, _.keys(tmpBoxes)).then(function () {
				created = true;
			});

			waitsFor(function () { return created; }, 'the boxes to be created', boxcreations * 2000);
			runs(function () { expect(_.values(tmpBoxes).length) === tmpBoxesDfds.length; });
		});

		describe('box collection', function () {
			it('should have ' + (boxcreations + 1) + ' boxes in the box collection')
		});

		it('should be able to delete those boxes')

		it('should fail to create a box if it already exists', function () {
			var failed;
			store1.create_box(testboxname).fail(function () {
				failed = true;
			});
			waitsFor(function () { return failed; }, 'the box to not have been created', 500);
			runs(function () { expect(failed).toBe(true); });
		});

		it('should have this box within another store (should auto-update)', function () {
			waitsFor(function () { return store2.boxes().get(testboxname); }, 'another store to list the new box', 1000);
			runs(function () { expect(store2.boxes().get(testboxname)).toBeDefined(); });
		});

		describe('box collection', function () {
			it('should have only one box in the box collection', function () {
				expect(store1.boxes().length).toBe(1);
			});
		});

		// hack
		//testboxname = 'blah';

		describe('box', function () {
			var s1box, s2box;
			it('should be defined', function () {
				var b = store1.get_box(testboxname);
				expect(b).toBeDefined();
			});

			it('should be a Backbone Model')

			it('should have a cache of objects')

			describe('Object Cache', function () {
				it('should be a Backbone Collection')
			})

			it('should have a list of objects')

			describe('Object List', function () {
				it('should be an array')
			});

			it('should have a collection of files')

			describe('File Collection', function () {
				it('should be a Backbone Collection')
			})

			// making it sure it exists
			it('should be retreivable', function () {
				store1.get_box(testboxname).then(function (b) { s1box = b; });
				store2.get_box(testboxname).then(function (b) { s2box = b; });
				waitsFor(function () { return s1box && s2box; }, 'the box to be fetched', 500);
				runs(function () {
					expect(s1box).toBeDefined();
					expect(s2box).toBeDefined();
				});
			});

			it('should allow an object to be created', function () {
				var obj;
				s1box.get_obj('test1').then(function(o) { obj = o; });
				waitsFor(function () { return obj; }, 'the object to be created', 500);
				runs(function () { expect(obj).toBeDefined(); });
			});

			/*it('should not allow an object to be created if it already exists', function () {
				var obj;
				s1box.get_obj('test1').then(function(o) { obj = o; });
				waitsFor(function () { return obj; });
				runs(function () { expect(obj).toBeDefined(); });
			});*/

			describe('object', function () {
				var s1obj, s2obj;
				it('should allow the object to be fetched', function () {
					s1box.get_obj('test1').then(function (o) { s1obj = o; });
					waitsFor(function () { return s1obj; }, 'the object to be fetched', 500);
					runs(function () {
						expect(s1obj).toBeDefined();
					});
				});

				it('should allow the object to be created', function () {
					var saved;
					s1obj.save({ value: 99 }).then(function () { saved = true; });
					waitsFor(function () { return saved; }, 'the object to have changed', 500);
					runs(function () { expect(s1obj.get('value')[0]).toBe(99); });
				});
				it('should allow another store (store 2) to load the object', function () {
					s2box.get_obj('test1').then(function (o) { s2obj = o; });
					waitsFor(function () { return s2obj; }, 'the object to be fetched', 500);
					runs(function () { expect(s2obj).toBeDefined(); });
				});
				it('should be up-to-date in store 2', function () {
					waitsFor(function () { return s2obj.get('value') && s2obj.get('value')[0] === 99; },
							'the object to be up-to-date', 500);
					runs(function () { expect(s2obj.get('value')[0]).toBe(99); });
				});
				it('should not be using the same cache between stores', function () {
					expect(s1obj.attributes).not.toBe(s2obj.attributes);
				});
				it('should allow store 2 to edit the object', function () {
					var saved;
					s2obj.save({ value: 97 }).then(function () { saved = true; });
					waitsFor(function () { return saved; }, 'the object to have changed', 500);
					runs(function () { expect(s2obj.get('value')[0]).toBe(97); });
				});
				it('should have updated the object in store 1', function () {
					waitsFor(function () { return s1obj.get('value') && s1obj.get('value')[0] === 97; },
								'the object to be up-to-date', 500);
					runs(function () { expect(s1obj.get('value')[0]).toBe(97); });
				});

				it('should not allow two conflicting objects', function () {
					var s1obj, s2obj,
						passes = 0,
						fails = 0;
					s1box.get_obj('test2').then(function (o) { s1obj = o; });
					s2box.get_obj('test2').then(function (o) { s2obj = o; });
					s1box.save().then(function () { passes++; }).fail(function () { fails++; });
					s2box.save().then(function () { passes++; }).fail(function () { fails++; });
					waitsFor(function () { return passes + fails === 2; }, 'the boxes to have changed', 500);
					runs(function () {
						expect(passes).toBe(1);
						expect(fails).not.toBe(0);
					});
				});
			});

			it('should allow a file to be created')

			describe('file', function () {
				it('should allow the file to be fetched')

			})

			it('should be deletable', function () {
				var destroyed;
				s1box.destroy().then(function () { destroyed = true; });
				waitsFor(function () { return destroyed; }, 'the box to be deleted', 500);
				runs(function () { expect(s1box).not.toBeDefined(); });
			});
		});

		// create new object that didnt exist before, check to make sure it got created
		// ?? create new object that existed before, check to see if error // updates object
		// update object, make sure it propagate
		// coordinated testing: Can we ever do this??
		//   write an object, waitFor the thing to propagate to the other client
		// delete object, make sure it's dead, jim

		// it('getinfo', function() {
		// 	var gi;
		// 	runs(function() {
		// 		store.getInfo()
		// 			.then(function(x) { dump('getinfo ', x); gi = x; })
		// 			.fail(function(x) { console.error('fail logging in ', x); });
		// 	});
		// 	waitsFor(function() { return gi; });
		// 	runs(function() {
		// 		expect(gi).toBeDefined();
		// 		dump('done waiting ', gi);
		// 	});
		// });
		// it('should fetch boxes', function() {
		// 	var boxes;
		// 	runs(function() {
		// 		store.fetch()
		// 			.then(function(x) { dump('boxes ', x); boxes = store.boxes(); })
		// 			.fail(function(x) { console.error('fail logging in ', x); });
		// 	});
		// 	waitsFor(function() { return boxes; });
		// 	runs(function() {
		// 		dump('boxes >> ', boxes.map(function(x) { return x.get_id(); }));
		// 	});
		// });

	});

}(this.jasmine, this.$, this._, this.Backbone));
<|endoftext|>


<commit_before>/**
 * Module routing
 */
(function (angular) {
    'use strict';

    angular
        .module('refigureAuth')
        .run(appRun);

    var states = [{
        state: 'auth.signin',
        config: {
            url: '/signin',
            template: '<sign-in></sign-in>',
            data: {
                auth: true
            }
        }
    }, {
        state: 'auth.signup',
        config: {
            url: '/signup/:hash?',
            template: '<sign-up></sign-up>',
            data: {
                auth: true
            }
        }
    }, {
        state: 'auth.pwdreset',
        config: {
            url: '/passwordreset/:hash?',
            template: '<password-reset></password-reset>',
            data: {
                auth: true
            }
        }
    }, {
        state: 'auth.pwdset',
        config: {
            url: '/passwordset/:hash',
            template: '<password-reset></password-reset>',
            data: {
                auth: true
            }
        }
    }];

    appRun.$inject = [
        'routerHelper'
    ];

    function appRun(routerHelper) {

        routerHelper.trailingSlash();
        routerHelper.configureStates(getStates(), '/');

        //////////////////////

        function getStates() {
            return [{
                state: 'auth',
                config: {
                    abstract: true,
                    templateUrl: 'view/authPage.html'
                }
            }]
                .concat(states);
        }
    }
})(window.angular);
<commit_msg>+ default null value for optional params<commit_after>/**
 * Module routing
 */
(function (angular) {
    'use strict';

    angular
        .module('refigureAuth')
        .run(appRun);

    var states = [{
        state: 'auth.signin',
        config: {
            url: '/signin',
            template: '<sign-in></sign-in>',
            data: {
                auth: true
            }
        }
    }, {
        state: 'auth.signup',
        config: {
            url: '/signup/:hash',
            params:  {
                hash: {
                    value: null,
                    squash: true
                }
            },
            template: '<sign-up></sign-up>',
            data: {
                auth: true
            }
        }
    }, {
        state: 'auth.pwdreset',
        config: {
            url: '/passwordreset/:hash',
            params:  {
                hash: {
                    value: null,
                    squash: true
                }
            },
            template: '<password-reset></password-reset>',
            data: {
                auth: true
            }
        }
    }, {
        state: 'auth.pwdset',
        config: {
            url: '/passwordset/:hash',
            template: '<password-reset></password-reset>',
            data: {
                auth: true
            }
        }
    }];

    appRun.$inject = [
        'routerHelper'
    ];

    function appRun(routerHelper) {

        routerHelper.trailingSlash();
        routerHelper.configureStates(getStates(), '/');

        //////////////////////

        function getStates() {
            return [{
                state: 'auth',
                config: {
                    abstract: true,
                    templateUrl: 'view/authPage.html'
                }
            }]
                .concat(states);
        }
    }
})(window.angular);
<|endoftext|>