<commit_before>

describe("Delegatable", function() {
  it("delegate", function() {
    var C = Class.create(Delegatable, {
      initialize: function(arr) {
        this.arr = arr;
        this.delegate('arr', 'size', 'first', 'uniq');
      }
    });

    var z = new C([1,2,3,1]);

    expect(z.size()).toEqual(4);
    expect(z.first()).toEqual(1);
    expect(z.uniq()).toEqual([1,2,3]);
    expect(function(){z.last()}).toThrow();
  });

  it ("delegate with non method should throw error", function() {
    Class.create(Delegatable, {
        initialize: function(arr) {
          this.arr = arr;
          expect(
            function(){
              this.delegate('arr', 'length')
            }).toThrow();
        }
      });
  });

  it ("#delegate_alias", function() {
    var C = Class.create(Delegatable, {
      initialize: function(arr) {
        this.arr = arr;
        this.delegate_alias('arr', ['count'], ['size']);
      }
    });

    var z = new C([1,2,3]);

    expect(z.count()).toEqual(3);
  });

  it ("expection when as count not equal alias size", function() {
    Class.create(Delegatable, {
        initialize: function(arr) {
          this.arr = arr;
          expect(
            function(){
              this.delegate_alias('arr', ['count', 'first'], ['size']);
            }).toThrow();
        }
      });
  });
});<commit_msg>specs array and string<commit_after>

describe("Delegatable", function() {
  it("delegate", function() {
    var C = Class.create(Delegatable, {
      initialize: function(arr) {
        this.arr = arr;
        this.delegate('arr', 'size', 'first', 'uniq');
      }
    });

    var z = new C([1,2,3,1]);

    expect(z.size()).toEqual(4);
    expect(z.first()).toEqual(1);
    expect(z.uniq()).toEqual([1,2,3]);
    expect(function(){z.last()}).toThrow();
  });

  it ("delegate with non method should throw error", function() {
    Class.create(Delegatable, {
        initialize: function(arr) {
          this.arr = arr;
          expect(
            function(){
              this.delegate('arr', 'length')
            }).toThrow();
        }
      });
  });

  it ("#delegate_alias", function() {
    var C = Class.create(Delegatable, {
      initialize: function(arr) {
        this.arr = arr;
        this.delegate_alias('arr', ['count'], ['size']);
      }
    });

    var z = new C([1,2,3]);

    expect(z.count()).toEqual(3);
  });

  it ("expection when as count not equal alias size", function() {
    Class.create(Delegatable, {
        initialize: function(arr) {
          this.arr = arr;
          expect(
            function(){
              this.delegate_alias('arr', ['count', 'first'], ['size']);
            }).toThrow();
        }
      });
  });
});

describe("String", function() {

  it ("#isWorld", function() {
    expect("world".isWorld()).toBe(true);
    expect("".isWorld()).toBe(false);
    expect("<world>".isWorld()).toBe(false);
  });

  it ("#exec", function() {
    expect(
      "a is $0, b is $1, again $0".exec('A', 'B')
    ).toEqual("a is A, b is B, again A");

    expect(
      "$0".exec("A")
    ).toEqual("A");

    /*
    //pending
    expect(
      "1: \$0".exec("A")
    ).toEqual("1: \$0");
    */
    expect(
      function() {
        "$1".exec("1")
    }).toThrow();

  });

});

describe("Array", function() {
  it ("#second", function() {
    expect([1,2,3].second()).toEqual(2);
  });
})<|endoftext|>


<commit_before>// Tally Votes in JavaScript Pairing Challenge.

// I worked on this challenge with: Sabri Helal
// This challenge took me [2:30] hours.

// These are the votes cast by each student. Do not alter these objects here.
var votes = {
  "Alex": { president: "Bob", vicePresident: "Devin", secretary: "Gail", treasurer: "Kerry" },
  "Bob": { president: "Mary", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Cindy": { president: "Cindy", vicePresident: "Hermann", secretary: "Bob", treasurer: "Bob" },
  "Devin": { president: "Louise", vicePresident: "John", secretary: "Bob", treasurer: "Fred" },
  "Ernest": { president: "Fred", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Fred": { president: "Louise", vicePresident: "Alex", secretary: "Ivy", treasurer: "Ivy" },
  "Gail": { president: "Fred", vicePresident: "Alex", secretary: "Ivy", treasurer: "Bob" },
  "Hermann": { president: "Ivy", vicePresident: "Kerry", secretary: "Fred", treasurer: "Ivy" },
  "Ivy": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Gail" },
  "John": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Kerry" },
  "Kerry": { president: "Fred", vicePresident: "Mary", secretary: "Fred", treasurer: "Ivy" },
  "Louise": { president: "Nate", vicePresident: "Alex", secretary: "Mary", treasurer: "Ivy" },
  "Mary": { president: "Louise", vicePresident: "Oscar", secretary: "Nate", treasurer: "Ivy" },
  "Nate": { president: "Oscar", vicePresident: "Hermann", secretary: "Fred", treasurer: "Tracy" },
  "Oscar": { president: "Paulina", vicePresident: "Nate", secretary: "Fred", treasurer: "Ivy" },
  "Paulina": { president: "Louise", vicePresident: "Bob", secretary: "Devin", treasurer: "Ivy" },
  "Quintin": { president: "Fred", vicePresident: "Hermann", secretary: "Fred", treasurer: "Bob" },
  "Romanda": { president: "Louise", vicePresident: "Steve", secretary: "Fred", treasurer: "Ivy" },
  "Steve": { president: "Tracy", vicePresident: "Kerry", secretary: "Oscar", treasurer: "Xavier" },
  "Tracy": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Ullyses": { president: "Louise", vicePresident: "Hermann", secretary: "Ivy", treasurer: "Bob" },
  "Valorie": { president: "Wesley", vicePresident: "Bob", secretary: "Alex", treasurer: "Ivy" },
  "Wesley": { president: "Bob", vicePresident: "Yvonne", secretary: "Valorie", treasurer: "Ivy" },
  "Xavier": { president: "Steve", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Yvonne": { president: "Bob", vicePresident: "Zane", secretary: "Fred", treasurer: "Hermann" },
  "Zane": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Mary" }
}

// Tally the votes in voteCount.
var voteCount = {
  president: {},
  vicePresident: {},
  secretary: {},
  treasurer: {}
}

/* The name of each student receiving a vote for an office should become a property
of the respective office in voteCount.  After Alex's votes have been tallied,
voteCount would be ...
  var voteCount = {
    president: { Bob: 1 },
    vicePresident: { Devin: 1 },
    secretary: { Gail: 1 },
    treasurer: { Kerry: 1 }
  }
*/

/* Once the votes have been tallied, assign each officer position the name of the
student who received the most votes. */
var officers = {
  president: undefined,
  vicePresident: undefined,
  secretary: undefined,
  treasurer: undefined
}

// // Pseudocode
// Iterate through votes objects,
// Counting for each property within the object,
// FOR each property within the object we record each student's vote and
// add that to the variable voteCount
//Once tallied, we assign the winners per property to the officers variable

// __________________________________________
// Initial Solution
// var tallyCount = function(votes){
// for ( var name in votes){
//   var voters = votes[name];
// for ( var position in voters){
//   var vote = voters[position];

//  if(position === "president"){
//             if(voteCount.president.hasOwnProperty(vote)){
//               voteCount.president[vote] = voteCount.president[vote] + 1;}
//             else {voteCount.president[vote] = 1; }
//           } //if position == president end bracket

//           if(position === "vicePresident"){
//             if(voteCount.vicePresident.hasOwnProperty(vote)){
//               voteCount.vicePresident[vote] = voteCount.vicePresident[vote] + 1;}
//             else {voteCount.vicePresident[vote] = 1;  }
//           }

//           if(position === "secretary"){
//             if(voteCount.secretary.hasOwnProperty(vote)){
//               voteCount.secretary[vote] = voteCount.secretary[vote] + 1;}
//             else {voteCount.secretary[vote] = 1; }
//           }

//           if(position === "treasurer"){
//             if(voteCount.treasurer.hasOwnProperty(vote)){
//               voteCount.treasurer[vote] = voteCount.treasurer[vote] + 1;}
//             else {voteCount.treasurer[vote] = 1; }
//           }

//        }
//     }

//     return voteCount;
// };

// tallyCount(votes);

// var winner = function(){
//   for (var office in voteCount){
//     var tally = voteCount[office]
//     var count = 0
//     var win;

//   for ( var key in tally){
//     if((tally[key]) > count){
//       count = tally[key];
//       win = key;
//     }
//   }
//   officers[office] = win;
//   }
// };
// winner();

//  __________________________________________
// Refactored Solution

var positions = ["president", "vicePresident", "secretary", "treasurer"];
var tallyCounts = function() {
for (var name in votes) {
for (var i=0; i<positions.length; i++) {
var position = positions[i];
if ((voteCount[position]).hasOwnProperty(votes[name][position])) {
        voteCount[position][votes[name][position]]++;
      }
else {
        voteCount[position][votes[name][position]] = 1;
      }
    }
  }
};
tallyCounts();

var winner = function(){
  for (var office in voteCount){
    var tally = voteCount[office]
    var count = 0
    var win;

  for ( var key in tally){
    if((tally[key]) > count){
      count = tally[key];
      win = key;
    }
  }
  officers[office] = win;
  }
};
winner();

// __________________________________________
// Reflection

// What did you learn about iterating over nested objects in JavaScript?
// Were you able to find useful methods to help you with this?
// What concepts were solidified in the process of working through this challenge?

// __________________________________________
// Test Code:  Do not alter code below this line.

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (voteCount.president["Bob"] === 3),
  "Bob should receive three votes for President.",
  "1. "
)

assert(
  (voteCount.vicePresident["Bob"] === 2),
  "Bob should receive two votes for Vice President.",
  "2. "
)

assert(
  (voteCount.secretary["Bob"] === 2),
  "Bob should receive two votes for Secretary.",
  "3. "
)

assert(
  (voteCount.treasurer["Bob"] === 4),
  "Bob should receive four votes for Treasurer.",
  "4. "
)

assert(
  (officers.president === "Louise"),
  "Louise should be elected President.",
  "5. "
)

assert(
  (officers.vicePresident === "Hermann"),
  "Hermann should be elected Vice President.",
  "6. "
)

assert(
  (officers.secretary === "Fred"),
  "Fred should be elected Secretary.",
  "7. "
)

assert(
  (officers.treasurer === "Ivy"),
  "Ivy should be elected Treasurer.",
  "8. "
)
<commit_msg>reflection added<commit_after>// Tally Votes in JavaScript Pairing Challenge.

// I worked on this challenge with: Sabri Helal
// This challenge took me [2:30] hours.

// These are the votes cast by each student. Do not alter these objects here.
var votes = {
  "Alex": { president: "Bob", vicePresident: "Devin", secretary: "Gail", treasurer: "Kerry" },
  "Bob": { president: "Mary", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Cindy": { president: "Cindy", vicePresident: "Hermann", secretary: "Bob", treasurer: "Bob" },
  "Devin": { president: "Louise", vicePresident: "John", secretary: "Bob", treasurer: "Fred" },
  "Ernest": { president: "Fred", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Fred": { president: "Louise", vicePresident: "Alex", secretary: "Ivy", treasurer: "Ivy" },
  "Gail": { president: "Fred", vicePresident: "Alex", secretary: "Ivy", treasurer: "Bob" },
  "Hermann": { president: "Ivy", vicePresident: "Kerry", secretary: "Fred", treasurer: "Ivy" },
  "Ivy": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Gail" },
  "John": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Kerry" },
  "Kerry": { president: "Fred", vicePresident: "Mary", secretary: "Fred", treasurer: "Ivy" },
  "Louise": { president: "Nate", vicePresident: "Alex", secretary: "Mary", treasurer: "Ivy" },
  "Mary": { president: "Louise", vicePresident: "Oscar", secretary: "Nate", treasurer: "Ivy" },
  "Nate": { president: "Oscar", vicePresident: "Hermann", secretary: "Fred", treasurer: "Tracy" },
  "Oscar": { president: "Paulina", vicePresident: "Nate", secretary: "Fred", treasurer: "Ivy" },
  "Paulina": { president: "Louise", vicePresident: "Bob", secretary: "Devin", treasurer: "Ivy" },
  "Quintin": { president: "Fred", vicePresident: "Hermann", secretary: "Fred", treasurer: "Bob" },
  "Romanda": { president: "Louise", vicePresident: "Steve", secretary: "Fred", treasurer: "Ivy" },
  "Steve": { president: "Tracy", vicePresident: "Kerry", secretary: "Oscar", treasurer: "Xavier" },
  "Tracy": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Ullyses": { president: "Louise", vicePresident: "Hermann", secretary: "Ivy", treasurer: "Bob" },
  "Valorie": { president: "Wesley", vicePresident: "Bob", secretary: "Alex", treasurer: "Ivy" },
  "Wesley": { president: "Bob", vicePresident: "Yvonne", secretary: "Valorie", treasurer: "Ivy" },
  "Xavier": { president: "Steve", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Yvonne": { president: "Bob", vicePresident: "Zane", secretary: "Fred", treasurer: "Hermann" },
  "Zane": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Mary" }
}

// Tally the votes in voteCount.
var voteCount = {
  president: {},
  vicePresident: {},
  secretary: {},
  treasurer: {}
}

/* The name of each student receiving a vote for an office should become a property
of the respective office in voteCount.  After Alex's votes have been tallied,
voteCount would be ...
  var voteCount = {
    president: { Bob: 1 },
    vicePresident: { Devin: 1 },
    secretary: { Gail: 1 },
    treasurer: { Kerry: 1 }
  }
*/

/* Once the votes have been tallied, assign each officer position the name of the
student who received the most votes. */
var officers = {
  president: undefined,
  vicePresident: undefined,
  secretary: undefined,
  treasurer: undefined
}

// // Pseudocode
// Iterate through votes objects,
// Counting for each property within the object,
// FOR each property within the object we record each student's vote and
// add that to the variable voteCount
//Once tallied, we assign the winners per property to the officers variable

// __________________________________________
// Initial Solution
// var tallyCount = function(votes){
// for ( var name in votes){
//   var voters = votes[name];
// for ( var position in voters){
//   var vote = voters[position];

//  if(position === "president"){
//             if(voteCount.president.hasOwnProperty(vote)){
//               voteCount.president[vote] = voteCount.president[vote] + 1;}
//             else {voteCount.president[vote] = 1; }
//           } //if position == president end bracket

//           if(position === "vicePresident"){
//             if(voteCount.vicePresident.hasOwnProperty(vote)){
//               voteCount.vicePresident[vote] = voteCount.vicePresident[vote] + 1;}
//             else {voteCount.vicePresident[vote] = 1;  }
//           }

//           if(position === "secretary"){
//             if(voteCount.secretary.hasOwnProperty(vote)){
//               voteCount.secretary[vote] = voteCount.secretary[vote] + 1;}
//             else {voteCount.secretary[vote] = 1; }
//           }

//           if(position === "treasurer"){
//             if(voteCount.treasurer.hasOwnProperty(vote)){
//               voteCount.treasurer[vote] = voteCount.treasurer[vote] + 1;}
//             else {voteCount.treasurer[vote] = 1; }
//           }

//        }
//     }

//     return voteCount;
// };

// tallyCount(votes);

// var winner = function(){
//   for (var office in voteCount){
//     var tally = voteCount[office]
//     var count = 0
//     var win;

//   for ( var key in tally){
//     if((tally[key]) > count){
//       count = tally[key];
//       win = key;
//     }
//   }
//   officers[office] = win;
//   }
// };
// winner();

//  __________________________________________
// Refactored Solution

var positions = ["president", "vicePresident", "secretary", "treasurer"];
var tallyCounts = function() {
for (var name in votes) {
for (var i=0; i<positions.length; i++) {
var position = positions[i];
if ((voteCount[position]).hasOwnProperty(votes[name][position])) {
        voteCount[position][votes[name][position]]++;
      }
else {
        voteCount[position][votes[name][position]] = 1;
      }
    }
  }
};
tallyCounts();

var winner = function(){
  for (var office in voteCount){
    var tally = voteCount[office]
    var count = 0
    var win;

  for ( var key in tally){
    if((tally[key]) > count){
      count = tally[key];
      win = key;
    }
  }
  officers[office] = win;
  }
};
winner();

// __________________________________________
// Reflection

// What did you learn about iterating over nested objects in JavaScript?
// for ..in function it is pretty helpful when iterating over nested objects.
// Were you able to find useful methods to help you with this?
// We did this with for loops and if statement.
// What concepts were solidified in the process of working through this challenge?
// This challenge was exausting and very confusing , still many things are not very clear ...i underestimated JS for sure .

// __________________________________________
// Test Code:  Do not alter code below this line.

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (voteCount.president["Bob"] === 3),
  "Bob should receive three votes for President.",
  "1. "
)

assert(
  (voteCount.vicePresident["Bob"] === 2),
  "Bob should receive two votes for Vice President.",
  "2. "
)

assert(
  (voteCount.secretary["Bob"] === 2),
  "Bob should receive two votes for Secretary.",
  "3. "
)

assert(
  (voteCount.treasurer["Bob"] === 4),
  "Bob should receive four votes for Treasurer.",
  "4. "
)

assert(
  (officers.president === "Louise"),
  "Louise should be elected President.",
  "5. "
)

assert(
  (officers.vicePresident === "Hermann"),
  "Hermann should be elected Vice President.",
  "6. "
)

assert(
  (officers.secretary === "Fred"),
  "Fred should be elected Secretary.",
  "7. "
)

assert(
  (officers.treasurer === "Ivy"),
  "Ivy should be elected Treasurer.",
  "8. "
)
<|endoftext|>


<commit_before>// Tally Votes in JavaScript Pairing Challenge.

// I worked on this challenge with Ryan Smith:
// This challenge took me [#] hours.

// These are the votes cast by each student. Do not alter these objects here.
var votes = {
  "Alex": { president: "Bob", vicePresident: "Devin", secretary: "Gail", treasurer: "Kerry" },
  "Bob": { president: "Mary", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Cindy": { president: "Cindy", vicePresident: "Hermann", secretary: "Bob", treasurer: "Bob" },
  "Devin": { president: "Louise", vicePresident: "John", secretary: "Bob", treasurer: "Fred" },
  "Ernest": { president: "Fred", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Fred": { president: "Louise", vicePresident: "Alex", secretary: "Ivy", treasurer: "Ivy" },
  "Gail": { president: "Fred", vicePresident: "Alex", secretary: "Ivy", treasurer: "Bob" },
  "Hermann": { president: "Ivy", vicePresident: "Kerry", secretary: "Fred", treasurer: "Ivy" },
  "Ivy": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Gail" },
  "John": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Kerry" },
  "Kerry": { president: "Fred", vicePresident: "Mary", secretary: "Fred", treasurer: "Ivy" },
  "Louise": { president: "Nate", vicePresident: "Alex", secretary: "Mary", treasurer: "Ivy" },
  "Mary": { president: "Louise", vicePresident: "Oscar", secretary: "Nate", treasurer: "Ivy" },
  "Nate": { president: "Oscar", vicePresident: "Hermann", secretary: "Fred", treasurer: "Tracy" },
  "Oscar": { president: "Paulina", vicePresident: "Nate", secretary: "Fred", treasurer: "Ivy" },
  "Paulina": { president: "Louise", vicePresident: "Bob", secretary: "Devin", treasurer: "Ivy" },
  "Quintin": { president: "Fred", vicePresident: "Hermann", secretary: "Fred", treasurer: "Bob" },
  "Romanda": { president: "Louise", vicePresident: "Steve", secretary: "Fred", treasurer: "Ivy" },
  "Steve": { president: "Tracy", vicePresident: "Kerry", secretary: "Oscar", treasurer: "Xavier" },
  "Tracy": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Ullyses": { president: "Louise", vicePresident: "Hermann", secretary: "Ivy", treasurer: "Bob" },
  "Valorie": { president: "Wesley", vicePresident: "Bob", secretary: "Alex", treasurer: "Ivy" },
  "Wesley": { president: "Bob", vicePresident: "Yvonne", secretary: "Valorie", treasurer: "Ivy" },
  "Xavier": { president: "Steve", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Yvonne": { president: "Bob", vicePresident: "Zane", secretary: "Fred", treasurer: "Hermann" },
  "Zane": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Mary" }
}

// Tally the votes in voteCount.
var voteCount = {
  president: {},
  vicePresident: {},
  secretary: {},
  treasurer: {}
}

/* The name of each student receiving a vote for an office should become a property
of the respective office in voteCount.  After Alex's votes have been tallied,
voteCount would be ...
  var voteCount = {
    president: { Bob: 1},
    vicePresident: { Devin: 1 },
    secretary: { Gail: 1 },
    treasurer: { Kerry: 1 }
  }
*/

/* Once the votes have been tallied, assign each officer position the name of the
student who received the most votes. */
var officers = {
  president: undefined,
  vicePresident: undefined,
  secretary: undefined,
  treasurer: undefined
}

// Pseudocode
// Iterate over the voters object
// For each vote for President

// voteCount[office][candidate] += 1

// __________________________________________
// Initial Solution

//console.log(votes.getOwnPropertyNames());

for (var voter in votes) {
  for(var office in votes[voter]){
    if (voteCount[office][votes[voter][office]] === undefined) {
      voteCount[office][votes[voter][office]] = 0;
    }
    voteCount[office][votes[voter][office]] += 1;
  }
}

/*
1. Iterate over voteCount object
2. Run second inside of the office type object
3. Check the key values for the max.
4. Return the name with max vote count.

*/

for (var officeType in voteCount) {
  var ballotVote = 0;
  var winner = null;
  for(var candidate in voteCount[officeType]){
    if (voteCount[officeType][candidate] > ballotVote) {
      ballotVote = voteCount[officeType][candidate];
      winner = candidate;
    }
  }
  officers[officeType] = winner;
}

console.log(voteCount);
console.log(officers);

// __________________________________________
// Refactored Solution

// __________________________________________
// Reflection

// __________________________________________
// Test Code:  Do not alter code below this line.

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (voteCount.president["Bob"] === 3),
  "Bob should receive three votes for President.",
  "1. "
)

assert(
  (voteCount.vicePresident["Bob"] === 2),
  "Bob should receive two votes for Vice President.",
  "2. "
)

assert(
  (voteCount.secretary["Bob"] === 2),
  "Bob should receive two votes for Secretary.",
  "3. "
)

assert(
  (voteCount.treasurer["Bob"] === 4),
  "Bob should receive four votes for Treasurer.",
  "4. "
)

assert(
  (officers.president === "Louise"),
  "Louise should be elected President.",
  "5. "
)

assert(
  (officers.vicePresident === "Hermann"),
  "Hermann should be elected Vice President.",
  "6. "
)

assert(
  (officers.secretary === "Fred"),
  "Fred should be elected Secretary.",
  "7. "
)

assert(
  (officers.treasurer === "Ivy"),
  "Ivy should be elected Treasurer.",
  "8. "
)<commit_msg>Tally Votes Javascript<commit_after>// Tally Votes in JavaScript Pairing Challenge.

// I worked on this challenge with Ryan Smith:
// This challenge took me [#] hours.

// These are the votes cast by each student. Do not alter these objects here.
var votes = {
  "Alex": { president: "Bob", vicePresident: "Devin", secretary: "Gail", treasurer: "Kerry" },
  "Bob": { president: "Mary", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Cindy": { president: "Cindy", vicePresident: "Hermann", secretary: "Bob", treasurer: "Bob" },
  "Devin": { president: "Louise", vicePresident: "John", secretary: "Bob", treasurer: "Fred" },
  "Ernest": { president: "Fred", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Fred": { president: "Louise", vicePresident: "Alex", secretary: "Ivy", treasurer: "Ivy" },
  "Gail": { president: "Fred", vicePresident: "Alex", secretary: "Ivy", treasurer: "Bob" },
  "Hermann": { president: "Ivy", vicePresident: "Kerry", secretary: "Fred", treasurer: "Ivy" },
  "Ivy": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Gail" },
  "John": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Kerry" },
  "Kerry": { president: "Fred", vicePresident: "Mary", secretary: "Fred", treasurer: "Ivy" },
  "Louise": { president: "Nate", vicePresident: "Alex", secretary: "Mary", treasurer: "Ivy" },
  "Mary": { president: "Louise", vicePresident: "Oscar", secretary: "Nate", treasurer: "Ivy" },
  "Nate": { president: "Oscar", vicePresident: "Hermann", secretary: "Fred", treasurer: "Tracy" },
  "Oscar": { president: "Paulina", vicePresident: "Nate", secretary: "Fred", treasurer: "Ivy" },
  "Paulina": { president: "Louise", vicePresident: "Bob", secretary: "Devin", treasurer: "Ivy" },
  "Quintin": { president: "Fred", vicePresident: "Hermann", secretary: "Fred", treasurer: "Bob" },
  "Romanda": { president: "Louise", vicePresident: "Steve", secretary: "Fred", treasurer: "Ivy" },
  "Steve": { president: "Tracy", vicePresident: "Kerry", secretary: "Oscar", treasurer: "Xavier" },
  "Tracy": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Ullyses": { president: "Louise", vicePresident: "Hermann", secretary: "Ivy", treasurer: "Bob" },
  "Valorie": { president: "Wesley", vicePresident: "Bob", secretary: "Alex", treasurer: "Ivy" },
  "Wesley": { president: "Bob", vicePresident: "Yvonne", secretary: "Valorie", treasurer: "Ivy" },
  "Xavier": { president: "Steve", vicePresident: "Hermann", secretary: "Fred", treasurer: "Ivy" },
  "Yvonne": { president: "Bob", vicePresident: "Zane", secretary: "Fred", treasurer: "Hermann" },
  "Zane": { president: "Louise", vicePresident: "Hermann", secretary: "Fred", treasurer: "Mary" }
}

// Tally the votes in voteCount.
var voteCount = {
  president: {},
  vicePresident: {},
  secretary: {},
  treasurer: {}
}

/* The name of each student receiving a vote for an office should become a property
of the respective office in voteCount.  After Alex's votes have been tallied,
voteCount would be ...
  var voteCount = {
    president: { Bob: 1},
    vicePresident: { Devin: 1 },
    secretary: { Gail: 1 },
    treasurer: { Kerry: 1 }
  }
*/

/* Once the votes have been tallied, assign each officer position the name of the
student who received the most votes. */
var officers = {
  president: undefined,
  vicePresident: undefined,
  secretary: undefined,
  treasurer: undefined
}

// Pseudocode
// Iterate over the voters object
// For each vote for President

// voteCount[office][candidate] += 1

// __________________________________________
// Initial Solution

//console.log(votes.getOwnPropertyNames());

for (var voter in votes) {
  for(var office in votes[voter]){
    if (voteCount[office][votes[voter][office]] === undefined) {
      voteCount[office][votes[voter][office]] = 0;
    }
    voteCount[office][votes[voter][office]] += 1;
  }
}

/*
1. Iterate over voteCount object
2. Run second inside of the office type object
3. Check the key values for the max.
4. Return the name with max vote count.

*/

for (var officeType in voteCount) {
  var ballotVote = 0;
  var winner = null;
  for(var candidate in voteCount[officeType]){
    if (voteCount[officeType][candidate] > ballotVote) {
      ballotVote = voteCount[officeType][candidate];
      winner = candidate;
    }
  }
  officers[officeType] = winner;
}

console.log(voteCount);
console.log(officers);

// __________________________________________
// Refactored Solution

// __________________________________________
// Reflection
/*
What did you learn about iterating over nested objects in JavaScript?
[RS] It can be very initmidating and difficult. Learning the difference between bracket and dot notation helps signicicantly.

Were you able to find useful methods to help you with this?
[RS] Yes, the for each loop.

What concepts were solidified in the process of working through this challenge?
[RS] Using objects in javascript and updating count values.

*/

// __________________________________________
// Test Code:  Do not alter code below this line.

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (voteCount.president["Bob"] === 3),
  "Bob should receive three votes for President.",
  "1. "
)

assert(
  (voteCount.vicePresident["Bob"] === 2),
  "Bob should receive two votes for Vice President.",
  "2. "
)

assert(
  (voteCount.secretary["Bob"] === 2),
  "Bob should receive two votes for Secretary.",
  "3. "
)

assert(
  (voteCount.treasurer["Bob"] === 4),
  "Bob should receive four votes for Treasurer.",
  "4. "
)

assert(
  (officers.president === "Louise"),
  "Louise should be elected President.",
  "5. "
)

assert(
  (officers.vicePresident === "Hermann"),
  "Hermann should be elected Vice President.",
  "6. "
)

assert(
  (officers.secretary === "Fred"),
  "Fred should be elected Secretary.",
  "7. "
)

assert(
  (officers.treasurer === "Ivy"),
  "Ivy should be elected Treasurer.",
  "8. "
)<|endoftext|>


<commit_before>"use babel";

helpers = require('atom-linter')
path    = require('path')

// This provides linter support for Perl 6 using linter
// Please see https://atom.io/packages/linter
module.exports =
class Perl6LinterProvider {

  constructor() {
    this.name          = 'Perl 6 Syntax Check'
    this.grammarScopes = ['source.perl6', 'source.perl6fe']
    this.scope         = 'file'
    this.lintOnFly     = true
  }

  lint(textEditor) {
    command = "perl6"
    args = ["-Ilib", '-c', "-"]

    // Find project directory for the text editor provided
    projectDir = atom.project.getDirectories().find(
      (dir) => {
        return dir.contains(textEditor.getPath() )
      }
    )
    projectDir = projectDir && projectDir.path ? projectDir.path : null;

    options = {
      cwd: projectDir,
      stream : "",
      stdin  : textEditor.getText()
    }
    return helpers.exec(command, args, options).then( (output) => {

      // return nothing if no errors are found
      if (output.stdout.match(/Syntax OK\n?/i) && output.stderr == "") {
        return []
      }

      // Try to find the error message and line number
      regex = /.+?[\r\n]((?:.|[\r\n])+\s+at.+?(\d+)\s+.+)/
      stderr = output.stderr
      match = regex.exec(stderr)
      if (match) {
        // Success; Remove the ansi escape sequence noise from the message
        message = match[1]
        line    = match[2] - 1
      } else {
        // We failed, at least show the message without line number information
        message = stderr.replace(/===(.*)===/, "")
        line    = 0
      }

      // The error message is for the whole line
      colEnd = textEditor.getBuffer().lineLengthForRow(line)

      // Return the message to atom lint plugin
      return [{
        type: 'Error',
        text: message.replace(/\x1b\[\d+(;\d+)?m/g, ""),
        range:[[line, 0], [line, colEnd]],
        filePath: textEditor.getPath()
      }]
    })
  }
}
<commit_msg>small fix for linter<commit_after>"use babel";

helpers = require('atom-linter')
path    = require('path')

// This provides linter support for Perl 6 using linter
// Please see https://atom.io/packages/linter
module.exports =
class Perl6LinterProvider {

  constructor() {
    this.name          = 'Perl 6 Syntax Check'
    this.grammarScopes = ['source.perl6', 'source.perl6fe']
    this.scope         = 'file'
    this.lintOnFly     = true
  }

  lint(textEditor) {
    command = "perl6"
    args = ["-Ilib", '-c', "-"]

    // Find project directory for the text editor provided
    projectDir = atom.project.getDirectories().find(
      (dir) => {
        return dir.contains(textEditor.getPath() )
      }
    )
    projectDir = projectDir && projectDir.path ? projectDir.path : null;

    options = {
      cwd: projectDir,
      stream : "both",
      stdin  : textEditor.getText()
    }
    return helpers.exec(command, args, options).then( (output) => {

      // return nothing if no errors are found
      if (output.stdout.match(/Syntax OK\n?/i) && output.stderr == "") {
        return []
      }

      // Try to find the error message and line number
      regex = /.+?[\r\n]((?:.|[\r\n])+\s+at.+?(\d+)\s+.+)/
      stderr = output.stderr
      match = regex.exec(stderr)
      if (match) {
        // Success; Remove the ansi escape sequence noise from the message
        message = match[1]
        line    = match[2] - 1
      } else {
        // We failed, at least show the message without line number information
        message = stderr.replace(/===(.*)===/, "")
        line    = 0
      }

      // The error message is for the whole line
      colEnd = textEditor.getBuffer().lineLengthForRow(line)

      // Return the message to atom lint plugin
      return [{
        type: 'Error',
        text: message.replace(/\x1b\[\d+(;\d+)?m/g, ""),
        range:[[line, 0], [line, colEnd]],
        filePath: textEditor.getPath()
      }]
    })
  }
}
<|endoftext|>


<commit_before>module("Newgame", {
  'setup': function() {
    BMTestUtils.NewgamePre = BMTestUtils.getAllElements();

    BMTestUtils.setupFakeLogin();

    // Create the newgame_page div so functions have something to modify
    if (document.getElementById('newgame_page') == null) {
      $('body').append($('<div>', {'id': 'newgame_page', }));
    }
  },
  'teardown': function() {

    // Delete all elements we expect this module to create

    // JS objects
    delete Api.button;
    delete Api.player;
    delete Newgame.page;
    delete Newgame.form;

    // Page elements
    $('#newgame_page').remove();
    $('#newgame_page').empty();

    BMTestUtils.deleteEnvMessage();
    BMTestUtils.cleanupFakeLogin();

    // Fail if any other elements were added or removed
    BMTestUtils.NewgamePost = BMTestUtils.getAllElements();
    deepEqual(
      BMTestUtils.NewgamePost, BMTestUtils.NewgamePre,
      "After testing, the page should have no unexpected element changes");
  }
});

// pre-flight test of whether the Newgame module has been loaded
test("test_Newgame_is_loaded", function() {
  ok(Newgame, "The Newgame namespace exists");
});

// Newgame.showNewgamePage() does not directly take a callback,
// but, under the hood, it calls a function (Newgame.getNewgameData())
// which calls a chain of two callbacks in succession.
// It appears that QUnit's asynchronous testing framework can't
// handle that situation, so don't use it --- instead turn off
// asynchronous processing in AJAX while we test this one.
test("test_Newgame.showNewgamePage", function() {
  $.ajaxSetup({ async: false });
  Newgame.showNewgamePage();
  var item = document.getElementById('newgame_page');
  equal(item.nodeName, "DIV",
        "#newgame_page is a div after showNewgamePage() is called");
  $.ajaxSetup({ async: true });
});

test("test_Newgame.showNewgamePage_no_page_element", function() {

  // Remove page element to make sure the function readds it
  $('#newgame_page').remove();
  $('#newgame_page').empty();

  $.ajaxSetup({ async: false });
  Newgame.showNewgamePage();
  var item = document.getElementById('newgame_page');
  equal(item.nodeName, "DIV",
        "#newgame_page is a div after showNewgamePage() is called");
  $.ajaxSetup({ async: true });
});

test("test_Newgame.showNewgamePage_logged_out", function() {

  // Undo the fake login data
  Login.player = null;
  Login.logged_in = false;

  $.ajaxSetup({ async: false });
  Newgame.showNewgamePage();
  var item = document.getElementById('newgame_page');
  equal(item.nodeName, "DIV",
        "#newgame_page is a div after showNewgamePage() is called");
  $.ajaxSetup({ async: true });
});

asyncTest("test_Newgame.getNewgameData", function() {
  Newgame.getNewgameData(function() {
    ok(Api.player, "player list is parsed from server");
    ok(Api.button, "button list is parsed from server");
    start();
  });
});

asyncTest("test_Newgame.showPage", function() {
  Newgame.getNewgameData(function() {
    Newgame.showPage();
    var htmlout = Newgame.page.html();
    ok(htmlout.length > 0,
       "The created page should have nonzero contents");
    start();
  });
});

asyncTest("test_Newgame.showPage_button_load_failed", function() {
  Newgame.getNewgameData(function() {
    Api.button.load_status = 'failed';
    Newgame.showPage();
    var htmlout = Newgame.page.html();
    ok(htmlout.length > 0,
       "The created page should have nonzero contents");
    start();
  });
});

asyncTest("test_Newgame.showPage_player_load_failed", function() {
  Newgame.getNewgameData(function() {
    Api.player.load_status = 'failed';
    Newgame.showPage();
    var htmlout = Newgame.page.html();
    ok(htmlout.length > 0,
       "The created page should have nonzero contents");
    start();
  });
});

asyncTest("test_Newgame.layoutPage", function() {
  Newgame.getNewgameData(function() {
    Newgame.page = $('<div>');
    Newgame.page.append($('<p>', {'text': 'hi world', }));
    Newgame.layoutPage();
    var item = document.getElementById('newgame_page');
    equal(item.nodeName, "DIV",
          "#newgame_page is a div after layoutPage() is called");
    start();
  });
});

asyncTest("test_Newgame.actionLoggedOut", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionLoggedOut();
    equal(Newgame.form, null,
          "Form is null after the 'logged out' action is processed");
    start();
  });
});

asyncTest("test_Newgame.actionInternalErrorPage", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionInternalErrorPage();
    equal(Newgame.form, null,
          "Form is null after the 'internal error' action is processed");
    start();
  });
});

asyncTest("test_Newgame.actionCreateGame", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionCreateGame();
    equal(Newgame.form, Newgame.formCreateGame,
          "Form is set after the 'create game' action is processed");
    start();
  });
});

// The logic here is a little hairy: since Newgame.getNewgameData()
// takes a callback, we can use the normal asynchronous logic there.
// However, the POST done by our forms doesn't take a callback (it
// just redraws the page), so turn off asynchronous handling in
// AJAX while we test that, to make sure the test sees the return
// from the POST.
asyncTest("test_Newgame.formCreateGame", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionCreateGame();
    $('#opponent_name').val('tester2');
    $('#player_button').val('Crab');
    $('#opponent_button').val('John Kovalic');
    $.ajaxSetup({ async: false });
    $('#newgame_action_button').trigger('click');
    equal(
      Env.message.type, "success",
      "Newgame action succeeded when expected arguments were set");
    $.ajaxSetup({ async: true });
    start();
  });
});

asyncTest("test_Newgame.formCreateGame_no_vals", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionCreateGame();
    $.ajaxSetup({ async: false });
    $('#newgame_action_button').trigger('click');
    equal(
      Env.message.type, "error",
      "Newgame action failed when expected arguments were not set");
    $.ajaxSetup({ async: true });
    start();
  });
});

asyncTest("test_Newgame.formCreateGame_invalid_player", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionCreateGame();
    $('#opponent_name').val('nontester1');
    $('#player_button').val('Crab');
    $('#opponent_button').val('John Kovalic');
    $.ajaxSetup({ async: false });
    $('#newgame_action_button').trigger('click');
    equal(
      Env.message.type, "error",
      "Newgame action failed when opponent was not a known player");
    $.ajaxSetup({ async: true });
    start();
  });
});

asyncTest("test_Newgame.addLoggedOutPage", function() {
  ok(true, "INCOMPLETE: Test of Newgame.addLoggedOutPage not implemented");
  start();
});

asyncTest("test_Newgame.addInternalErrorPage", function() {
  ok(true, "INCOMPLETE: Test of Newgame.addInternalErrorPage not implemented");
  start();
});

asyncTest("test_Newgame.getSelectRow", function() {
  ok(true, "INCOMPLETE: Test of Newgame.getSelectRow not implemented");
  start();
});

test("test_Newgame.setCreateGameSuccessMessage", function() {
  Newgame.setCreateGameSuccessMessage(
    'test invocation succeeded',
    { 'gameId': 8, }
  );
  equal(Env.message.type, 'success', "set Env.message to a successful type");
});
<commit_msg>* continue trying to reach 100% test coverage of Newgame.js<commit_after>module("Newgame", {
  'setup': function() {
    BMTestUtils.NewgamePre = BMTestUtils.getAllElements();

    BMTestUtils.setupFakeLogin();

    // Create the newgame_page div so functions have something to modify
    if (document.getElementById('newgame_page') == null) {
      $('body').append($('<div>', {'id': 'newgame_page', }));
    }
  },
  'teardown': function() {

    // Delete all elements we expect this module to create

    // JS objects
    delete Api.button;
    delete Api.player;
    delete Newgame.page;
    delete Newgame.form;

    // Page elements
    $('#newgame_page').remove();
    $('#newgame_page').empty();

    BMTestUtils.deleteEnvMessage();
    BMTestUtils.cleanupFakeLogin();

    // Fail if any other elements were added or removed
    BMTestUtils.NewgamePost = BMTestUtils.getAllElements();
    deepEqual(
      BMTestUtils.NewgamePost, BMTestUtils.NewgamePre,
      "After testing, the page should have no unexpected element changes");
  }
});

// pre-flight test of whether the Newgame module has been loaded
test("test_Newgame_is_loaded", function() {
  ok(Newgame, "The Newgame namespace exists");
});

// Newgame.showNewgamePage() does not directly take a callback,
// but, under the hood, it calls a function (Newgame.getNewgameData())
// which calls a chain of two callbacks in succession.
// It appears that QUnit's asynchronous testing framework can't
// handle that situation, so don't use it --- instead turn off
// asynchronous processing in AJAX while we test this one.
test("test_Newgame.showNewgamePage", function() {
  $.ajaxSetup({ async: false });
  Newgame.showNewgamePage();
  var item = document.getElementById('newgame_page');
  equal(item.nodeName, "DIV",
        "#newgame_page is a div after showNewgamePage() is called");
  $.ajaxSetup({ async: true });
});

test("test_Newgame.showNewgamePage_no_page_element", function() {

  // Remove page element to make sure the function readds it
  $('#newgame_page').remove();
  $('#newgame_page').empty();

  $.ajaxSetup({ async: false });
  Newgame.showNewgamePage();
  var item = document.getElementById('newgame_page');
  equal(item.nodeName, "DIV",
        "#newgame_page is a div after showNewgamePage() is called");
  $.ajaxSetup({ async: true });
});

test("test_Newgame.showNewgamePage_logged_out", function() {

  // Undo the fake login data
  Login.player = null;
  Login.logged_in = false;

  $.ajaxSetup({ async: false });
  Newgame.showNewgamePage();
  var item = document.getElementById('newgame_page');
  equal(item.nodeName, "DIV",
        "#newgame_page is a div after showNewgamePage() is called");
  $.ajaxSetup({ async: true });
});

asyncTest("test_Newgame.getNewgameData", function() {
  Newgame.getNewgameData(function() {
    ok(Api.player, "player list is parsed from server");
    ok(Api.button, "button list is parsed from server");
    start();
  });
});

asyncTest("test_Newgame.showPage", function() {
  Newgame.getNewgameData(function() {
    Newgame.showPage();
    var htmlout = Newgame.page.html();
    ok(htmlout.length > 0,
       "The created page should have nonzero contents");
    start();
  });
});

asyncTest("test_Newgame.showPage_button_load_failed", function() {
  Newgame.getNewgameData(function() {
    Api.button.load_status = 'failed';
    Newgame.showPage();
    var htmlout = Newgame.page.html();
    ok(htmlout.length > 0,
       "The created page should have nonzero contents");
    start();
  });
});

asyncTest("test_Newgame.showPage_player_load_failed", function() {
  Newgame.getNewgameData(function() {
    Api.player.load_status = 'failed';
    Newgame.showPage();
    var htmlout = Newgame.page.html();
    ok(htmlout.length > 0,
       "The created page should have nonzero contents");
    start();
  });
});

asyncTest("test_Newgame.layoutPage", function() {
  Newgame.getNewgameData(function() {
    Newgame.page = $('<div>');
    Newgame.page.append($('<p>', {'text': 'hi world', }));
    Newgame.layoutPage();
    var item = document.getElementById('newgame_page');
    equal(item.nodeName, "DIV",
          "#newgame_page is a div after layoutPage() is called");
    start();
  });
});

asyncTest("test_Newgame.actionLoggedOut", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionLoggedOut();
    equal(Newgame.form, null,
          "Form is null after the 'logged out' action is processed");
    start();
  });
});

asyncTest("test_Newgame.actionInternalErrorPage", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionInternalErrorPage();
    equal(Newgame.form, null,
          "Form is null after the 'internal error' action is processed");
    start();
  });
});

asyncTest("test_Newgame.actionCreateGame", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionCreateGame();
    equal(Newgame.form, Newgame.formCreateGame,
          "Form is set after the 'create game' action is processed");
    start();
  });
});

// The logic here is a little hairy: since Newgame.getNewgameData()
// takes a callback, we can use the normal asynchronous logic there.
// However, the POST done by our forms doesn't take a callback (it
// just redraws the page), so turn off asynchronous handling in
// AJAX while we test that, to make sure the test sees the return
// from the POST.
asyncTest("test_Newgame.formCreateGame", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionCreateGame();
    $('#opponent_name').val('tester2');
    $('#player_button').val('Crab');
    $('#opponent_button').val('John Kovalic');
    $.ajaxSetup({ async: false });
    $('#newgame_action_button').trigger('click');
    equal(
      Env.message.type, "success",
      "Newgame action succeeded when expected arguments were set");
    $.ajaxSetup({ async: true });
    start();
  });
});

asyncTest("test_Newgame.formCreateGame_no_vals", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionCreateGame();
    $.ajaxSetup({ async: false });
    $('#newgame_action_button').trigger('click');
    equal(
      Env.message.type, "error",
      "Newgame action failed when expected arguments were not set");
    $.ajaxSetup({ async: true });
    start();
  });
});

asyncTest("test_Newgame.formCreateGame_no_buttons", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionCreateGame();
    $('#opponent_name').val('tester2');
    $.ajaxSetup({ async: false });
    $('#newgame_action_button').trigger('click');
    equal(
      Env.message.type, "error",
      "Newgame action failed when expected arguments were not set");
    $.ajaxSetup({ async: true });
    start();
  });
});

asyncTest("test_Newgame.formCreateGame_no_opponent_button", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionCreateGame();
    $('#opponent_name').val('tester2');
    $('#player_button').val('Crab');
    $.ajaxSetup({ async: false });
    $('#newgame_action_button').trigger('click');
    equal(
      Env.message.type, "error",
      "Newgame action failed when expected arguments were not set");
    $.ajaxSetup({ async: true });
    start();
  });
});

asyncTest("test_Newgame.formCreateGame_invalid_player", function() {
  Newgame.getNewgameData(function() {
    Newgame.actionCreateGame();
    $('#opponent_name').append(
      $('<option>', {
        'value': 'nontester1',
        'text': 'nontester1',
        'label': 'nontester1',
      })
    );
    $('#opponent_name').val('nontester1');
    $('#player_button').val('Crab');
    $('#opponent_button').val('John Kovalic');
    $.ajaxSetup({ async: false });
    $('#newgame_action_button').trigger('click');
    equal(
      Env.message.type, "error",
      "Newgame action failed when opponent was not a known player");
    equal(
      Env.message.text, "Specified opponent nontester1 is not recognized",
      "Newgame action failed when opponent was not a known player");
    $.ajaxSetup({ async: true });
    start();
  });
});

asyncTest("test_Newgame.addLoggedOutPage", function() {
  ok(true, "INCOMPLETE: Test of Newgame.addLoggedOutPage not implemented");
  start();
});

asyncTest("test_Newgame.addInternalErrorPage", function() {
  ok(true, "INCOMPLETE: Test of Newgame.addInternalErrorPage not implemented");
  start();
});

asyncTest("test_Newgame.getSelectRow", function() {
  ok(true, "INCOMPLETE: Test of Newgame.getSelectRow not implemented");
  start();
});

test("test_Newgame.setCreateGameSuccessMessage", function() {
  Newgame.setCreateGameSuccessMessage(
    'test invocation succeeded',
    { 'gameId': 8, }
  );
  equal(Env.message.type, 'success', "set Env.message to a successful type");
});
<|endoftext|>


<commit_before>/*global setImmediate:true*/

if (typeof setImmediate === 'undefined') {
    setImmediate = process.nextTick;
}

var BufferedStream = require('bufferedstream'),
    URL = require('url'),
    http = require('http'),
    _ = require('underscore'),
    messy = require('messy');

function lowerCaseHeaderNames(obj) {
    var resultObj = {};
    Object.keys(obj || {}).forEach(function (headerName) {
        resultObj[headerName.toLowerCase()] = obj[headerName];
    });
    return resultObj;
}

module.exports = function (expect) {
    expect.addType({
        name: 'messy.Headers',
        equal: function (headers1, headers2) {
            return headers1.equal(headers2);
        },
        identify: function (obj) {
            return obj instanceof messy.Headers;
        },
        inspect: function (output, headers, inspect) {
            headers.getNames().forEach(function (headerName) {
                headers.valuesByName[headerName].forEach(function (headerValue) {
                    output
                        .text(messy.formatHeaderName(headerName + ':'), 'gray')
                        .text(' ')
                        .text(headerValue, 'cyan')
                        .nl();
                });
            });
            return output;
        }
    }).addType({
        name: 'messy.HttpRequest',
        identify: function (obj) {
            return obj instanceof messy.HttpRequest;
        },
        equal: function (httpRequest1, httpRequest2) {
            return httpRequest1.equal(httpRequest2);
        },
        inspect: function (output, httpRequest, inspect) {
            output
                .text(httpRequest.method, 'blue')
                .text(' ')
                .text(httpRequest.url, 'gray')
                .text(' ')
                .text(httpRequest.protocolName, 'blue')
                .text('/')
                .text(httpRequest.protocolVersion, 'cyan')
                .nl();

            inspect(output, httpRequest.headers);
            return output;
        }
    }).addType({
        name: 'messy.HttpResponse',
        equal: function (httpResponse1, httpResponse2) {
            return httpResponse1.equal(httpResponse2);
        },
        identify: function (obj) {
            return obj instanceof messy.HttpResponse;
        },
        inspect: function (output, httpResponse, inspect) {
            output
                .text(httpRequest.protocolName, 'blue')
                .text('/')
                .text(httpRequest.protocolVersion, 'cyan')
                .text(' ')
                .text(httpResponse.statusCode, 'cyan')
                .text(' ')
                .text(httpResponse.statusMessage, 'yellow')
                .nl();
            inspect(output, httpResponse.headers);
            return output;
        }
    });

    expect.addAssertion('to be middleware that processes', function (expect, subject, value, _done) {
        this.errorMode = 'nested';
        expect(_done, 'to be a function');

        var doneCalled = false;

        function done() {
            if (!doneCalled) {
                doneCalled = true;
                return _done.apply(this, arguments);
            }
        }

        var requestProperties = typeof value.request === 'string' ? {url: value.request} : _.extend({}, value.request),
            httpRequest = new messy.HttpRequest({
                url: requestProperties.url,
                method: requestProperties.method,
                headers: requestProperties.headers
            });
        delete value.request;
        delete requestProperties.method;
        delete requestProperties.headers;
        delete requestProperties.url;
        if (typeof httpRequest.url === 'string') {
            var matchMethod = httpRequest.url.match(/^([A-Z]+) ([\s\S]*)$/);
            if (matchMethod) {
                httpRequest.method = httpRequest.method || matchMethod[1];
                httpRequest.url = matchMethod[2];
            }
        }
        httpRequest.method = httpRequest.method || 'GET';
        if (/^https?:\/\//.test(httpRequest.url)) {
            var urlObj = URL.parse(httpRequest.url);
            if (!httpRequest.headers.has('Host')) {
                httpRequest.headers.set('Host', urlObj.host);
            }
            if (urlObj.protocol === 'https:' && typeof requestProperties.https === 'undefined') {
                requestProperties.https = true;
            }
            httpRequest.url = urlObj.path;
        }

        var expectedResponseProperties;

        if (typeof value.response === 'number') {
            expectedResponseProperties = {statusCode: value.response};
        } else if (typeof value.response === 'string' || Buffer.isBuffer(value.response)) {
            expectedResponseProperties = {body: value.response};
        } else {
            expectedResponseProperties = _.extend({}, value.response);
        }
        delete value.response;

        var responseProperties = {},
            requestStream,
            body = requestProperties.body,
            req;

        if (typeof body !== 'undefined') {
            delete requestProperties.body;
            if (body.pipe) {
                requestStream = body;
                if (requestStream.constructor && requestStream.constructor.name === 'FormData') {
                    if (!httpRequest.headers.has('Content-Type')) {
                        httpRequest.headers.set('Content-Type', 'multipart/form-data; boundary=' + requestStream.getBoundary());
                        // form-data pauses its streams by default for some reason:
                        setImmediate(function () {
                            requestStream.resume();
                        });
                    }
                }
                if (!httpRequest.headers.has('Transfer-Encoding')) {
                    httpRequest.headers.set('Transfer-Encoding', 'chunked');
                }
                requestStream.on('data', function (chunk) {
                    req.emit('data', new Buffer(chunk, 'utf-8'));
                }).on('end', function () {
                    req.emit('end');
                }).on('error', function (err) {
                    req.emit('error', err);
                });
            } else {
                if (typeof body === 'object' && !Buffer.isBuffer(body)) {
                    if (!httpRequest.headers.has('Content-Type')) {
                        httpRequest.headers.set('Content-Type', 'application/json');
                    }
                    body = JSON.stringify(body);
                }

                if (!Buffer.isBuffer(body)) {
                    body = new Buffer(String(body), 'utf-8');
                }
                if (!httpRequest.headers.has('Content-Length') && !httpRequest.headers.has('Transfer-Encoding')) {
                    httpRequest.headers.set('Content-Length', String(body.length));
                }
                requestStream = new BufferedStream();
                setImmediate(function () {
                    req.emit('data', body);
                    req.emit('end');
                });
            }
        } else {
            requestStream = new BufferedStream();
            requestStream.destroy = function () {
                responseProperties.requestDestroyed = true;
            };
            setImmediate(function () {
                requestStream.emit('end');
                req.emit('end');
            });
        }

        req = new http.IncomingMessage(requestStream);
        req.connection = req.connection || {};
        req.connection.encrypted = !!requestProperties.https;
        delete requestProperties.https;
        req.connection.remoteAddress = requestProperties.remoteAddress || requestProperties.ip || '127.0.0.1';
        delete requestProperties.ip;
        delete requestProperties.remoteAddress;
        req.headers = {};
        httpRequest.headers.getNames().forEach(function (headerName) {
            // FIXME: Multiple?
            req.headers[headerName] = httpRequest.headers.get(headerName);
        });
        req.method = httpRequest.method;
        req.url = httpRequest.url;
        _.extend(req, requestProperties);

        var res = new http.ServerResponse(req);
        _.extend(res, requestProperties.res); // Allows for specifying eg. res.locals
        res.connection = new BufferedStream();
        res.connection._httpMessage = res;

        var nextCallCount = 0,
            next = function (err, _req, _res, _next) {
                nextCallCount += 1;
                if (typeof err === 'number') {
                    var statusCode = err;
                    err = new Error('' + statusCode);
                    err.statusCode = statusCode;
                }
                res.statusCode = err && (err.statusCode || err.status) || 404;
                doTheAssertions(err);
            };

        var responseBodyChunks = [],
            isDestroyed = false,
            isAsync = false;

        setImmediate(function () {
            isAsync = true;
        });

        function doTheAssertions(errorPassedToNext) {
            var context = {
                req: req,
                res: res,
                next: next,
                httpRequest: httpRequest,
                metadata: {
                    strictAsync: isAsync,
                    errorPassedToNext: false,
                    isDestroyed: isDestroyed,
                    nextCalled: nextCallCount > 0
                }
            };

            // Apparently setImmediate (or throwing an exception) is not an option here. If we don't call done, errors won't make it into mocha.
            var err = null;
            try {
                if (errorPassedToNext) {
                    context.metadata.errorPassedToNext = errorPassedToNext;
                    if (typeof value.errorPassedToNext !== 'undefined') {
                        if (value.errorPassedToNext === true) {
                            context.metadata.errorPassedToNext = true;
                        } else if (typeof value.errorPassedToNext === 'string') {
                            context.metadata.errorPassedToNext = errorPassedToNext.message;
                        } else {
                            context.metadata.errorPassedToNext = errorPassedToNext;
                        }
                    } else {
                        return setImmediate(function () {
                            done(errorPassedToNext);
                        });
                    }
                }
                var httpResponse = context.httpResponse = new messy.HttpResponse(res._header || undefined); // Avoid a parse error if empty string
                httpResponse.statusCode = res.statusCode;
                httpResponse.body = Buffer.concat(responseBodyChunks.map(function (bufferOrString) {
                    if (!Buffer.isBuffer(bufferOrString)) {
                        return new Buffer(String(bufferOrString), 'utf-8');
                    } else {
                        return bufferOrString;
                    }
                }));

                var httpResponseMatches = httpResponse.satisfies(expectedResponseProperties),
                    headersMatch = httpResponseMatches || httpResponse.headers.satisfy(expectedResponseProperties.headers),
                    bodyMatches = httpResponseMatches || !('body' in expectedResponseProperties) || httpResponse.satisfies({body: expectedResponseProperties.body});

                expect(context.metadata, 'to have properties', value);

                //delete expectedResponseProperties.body;
                // expect(responseProperties, 'to have properties', expectedResponseProperties);
                if (!headersMatch || !bodyMatches) {
                    // console.log(expect.inspect(httpResponse, expect.output.clone()).toString('ansi'));
                }
            } catch (assertionError) {
                err = assertionError;
            }
            setImmediate(function () {
                done(err, context);
            });
        }
        ['write', 'end', 'destroy'].forEach(function (methodName) {
            var orig = res[methodName];
            res[methodName] = function (chunk, encoding) {
                var returnValue = orig.apply(this, arguments);
                if (methodName !== 'destroy') {
                    if (encoding && !/^utf-?8$/i.test(encoding)) {
                        throw new Error('encoding parameter not supported except for "utf-8": ' + encoding);
                    }
                    if (chunk) {
                        responseBodyChunks.push(chunk);
                    }
                }
                if (methodName === 'end' || methodName === 'destroy') {
                    isDestroyed = methodName === 'destroy';
                    doTheAssertions();
                }
                return returnValue;
            };
        });
        subject(req, res, next);
    });
};
<commit_msg>Fixed typos & jshint<commit_after>/*global setImmediate:true*/

if (typeof setImmediate === 'undefined') {
    setImmediate = process.nextTick;
}

var BufferedStream = require('bufferedstream'),
    URL = require('url'),
    http = require('http'),
    _ = require('underscore'),
    messy = require('messy');

module.exports = function (expect) {
    expect.addType({
        name: 'messy.Headers',
        equal: function (headers1, headers2) {
            return headers1.equal(headers2);
        },
        identify: function (obj) {
            return obj instanceof messy.Headers;
        },
        inspect: function (output, headers, inspect) {
            headers.getNames().forEach(function (headerName) {
                headers.valuesByName[headerName].forEach(function (headerValue) {
                    output
                        .text(messy.formatHeaderName(headerName + ':'), 'gray')
                        .text(' ')
                        .text(headerValue, 'cyan')
                        .nl();
                });
            });
            return output;
        }
    }).addType({
        name: 'messy.HttpRequest',
        identify: function (obj) {
            return obj instanceof messy.HttpRequest;
        },
        equal: function (httpRequest1, httpRequest2) {
            return httpRequest1.equal(httpRequest2);
        },
        inspect: function (output, httpRequest, inspect) {
            output
                .text(httpRequest.method, 'blue')
                .text(' ')
                .text(httpRequest.url, 'gray')
                .text(' ')
                .text(httpRequest.protocolName, 'blue')
                .text('/')
                .text(httpRequest.protocolVersion, 'cyan')
                .nl();

            inspect(output, httpRequest.headers);
            return output;
        }
    }).addType({
        name: 'messy.HttpResponse',
        equal: function (httpResponse1, httpResponse2) {
            return httpResponse1.equal(httpResponse2);
        },
        identify: function (obj) {
            return obj instanceof messy.HttpResponse;
        },
        inspect: function (output, httpResponse, inspect) {
            output
                .text(httpResponse.protocolName, 'blue')
                .text('/')
                .text(httpResponse.protocolVersion, 'cyan')
                .text(' ')
                .text(httpResponse.statusCode, 'cyan')
                .text(' ')
                .text(httpResponse.statusMessage, 'yellow')
                .nl();
            inspect(output, httpResponse.headers);
            return output;
        }
    });

    expect.addAssertion('to be middleware that processes', function (expect, subject, value, _done) {
        this.errorMode = 'nested';
        expect(_done, 'to be a function');

        var doneCalled = false;

        function done() {
            if (!doneCalled) {
                doneCalled = true;
                return _done.apply(this, arguments);
            }
        }

        var requestProperties = typeof value.request === 'string' ? {url: value.request} : _.extend({}, value.request),
            httpRequest = new messy.HttpRequest({
                url: requestProperties.url,
                method: requestProperties.method,
                headers: requestProperties.headers
            });
        delete value.request;
        delete requestProperties.method;
        delete requestProperties.headers;
        delete requestProperties.url;
        if (typeof httpRequest.url === 'string') {
            var matchMethod = httpRequest.url.match(/^([A-Z]+) ([\s\S]*)$/);
            if (matchMethod) {
                httpRequest.method = httpRequest.method || matchMethod[1];
                httpRequest.url = matchMethod[2];
            }
        }
        httpRequest.method = httpRequest.method || 'GET';
        if (/^https?:\/\//.test(httpRequest.url)) {
            var urlObj = URL.parse(httpRequest.url);
            if (!httpRequest.headers.has('Host')) {
                httpRequest.headers.set('Host', urlObj.host);
            }
            if (urlObj.protocol === 'https:' && typeof requestProperties.https === 'undefined') {
                requestProperties.https = true;
            }
            httpRequest.url = urlObj.path;
        }

        var expectedResponseProperties;

        if (typeof value.response === 'number') {
            expectedResponseProperties = {statusCode: value.response};
        } else if (typeof value.response === 'string' || Buffer.isBuffer(value.response)) {
            expectedResponseProperties = {body: value.response};
        } else {
            expectedResponseProperties = _.extend({}, value.response);
        }
        delete value.response;

        var responseProperties = {},
            requestStream,
            body = requestProperties.body,
            req;

        if (typeof body !== 'undefined') {
            delete requestProperties.body;
            if (body.pipe) {
                requestStream = body;
                if (requestStream.constructor && requestStream.constructor.name === 'FormData') {
                    if (!httpRequest.headers.has('Content-Type')) {
                        httpRequest.headers.set('Content-Type', 'multipart/form-data; boundary=' + requestStream.getBoundary());
                        // form-data pauses its streams by default for some reason:
                        setImmediate(function () {
                            requestStream.resume();
                        });
                    }
                }
                if (!httpRequest.headers.has('Transfer-Encoding')) {
                    httpRequest.headers.set('Transfer-Encoding', 'chunked');
                }
                requestStream.on('data', function (chunk) {
                    req.emit('data', new Buffer(chunk, 'utf-8'));
                }).on('end', function () {
                    req.emit('end');
                }).on('error', function (err) {
                    req.emit('error', err);
                });
            } else {
                if (typeof body === 'object' && !Buffer.isBuffer(body)) {
                    if (!httpRequest.headers.has('Content-Type')) {
                        httpRequest.headers.set('Content-Type', 'application/json');
                    }
                    body = JSON.stringify(body);
                }

                if (!Buffer.isBuffer(body)) {
                    body = new Buffer(String(body), 'utf-8');
                }
                if (!httpRequest.headers.has('Content-Length') && !httpRequest.headers.has('Transfer-Encoding')) {
                    httpRequest.headers.set('Content-Length', String(body.length));
                }
                requestStream = new BufferedStream();
                setImmediate(function () {
                    req.emit('data', body);
                    req.emit('end');
                });
            }
        } else {
            requestStream = new BufferedStream();
            requestStream.destroy = function () {
                responseProperties.requestDestroyed = true;
            };
            setImmediate(function () {
                requestStream.emit('end');
                req.emit('end');
            });
        }

        req = new http.IncomingMessage(requestStream);
        req.connection = req.connection || {};
        req.connection.encrypted = !!requestProperties.https;
        delete requestProperties.https;
        req.connection.remoteAddress = requestProperties.remoteAddress || requestProperties.ip || '127.0.0.1';
        delete requestProperties.ip;
        delete requestProperties.remoteAddress;
        req.headers = {};
        httpRequest.headers.getNames().forEach(function (headerName) {
            // FIXME: Multiple?
            req.headers[headerName] = httpRequest.headers.get(headerName);
        });
        req.method = httpRequest.method;
        req.url = httpRequest.url;
        _.extend(req, requestProperties);

        var res = new http.ServerResponse(req);
        _.extend(res, requestProperties.res); // Allows for specifying eg. res.locals
        res.connection = new BufferedStream();
        res.connection._httpMessage = res;

        var nextCallCount = 0,
            next = function (err, _req, _res, _next) {
                nextCallCount += 1;
                if (typeof err === 'number') {
                    var statusCode = err;
                    err = new Error('' + statusCode);
                    err.statusCode = statusCode;
                }
                res.statusCode = err && (err.statusCode || err.status) || 404;
                doTheAssertions(err);
            };

        var responseBodyChunks = [],
            isDestroyed = false,
            isAsync = false;

        setImmediate(function () {
            isAsync = true;
        });

        function doTheAssertions(errorPassedToNext) {
            var context = {
                req: req,
                res: res,
                next: next,
                httpRequest: httpRequest,
                metadata: {
                    strictAsync: isAsync,
                    errorPassedToNext: false,
                    isDestroyed: isDestroyed,
                    nextCalled: nextCallCount > 0
                }
            };

            // Apparently setImmediate (or throwing an exception) is not an option here. If we don't call done, errors won't make it into mocha.
            var err = null;
            try {
                if (errorPassedToNext) {
                    context.metadata.errorPassedToNext = errorPassedToNext;
                    if (typeof value.errorPassedToNext !== 'undefined') {
                        if (value.errorPassedToNext === true) {
                            context.metadata.errorPassedToNext = true;
                        } else if (typeof value.errorPassedToNext === 'string') {
                            context.metadata.errorPassedToNext = errorPassedToNext.message;
                        } else {
                            context.metadata.errorPassedToNext = errorPassedToNext;
                        }
                    } else {
                        return setImmediate(function () {
                            done(errorPassedToNext);
                        });
                    }
                }
                var httpResponse = context.httpResponse = new messy.HttpResponse(res._header || undefined); // Avoid a parse error if empty string
                httpResponse.statusCode = res.statusCode;
                httpResponse.body = Buffer.concat(responseBodyChunks.map(function (bufferOrString) {
                    if (!Buffer.isBuffer(bufferOrString)) {
                        return new Buffer(String(bufferOrString), 'utf-8');
                    } else {
                        return bufferOrString;
                    }
                }));

                var httpResponseMatches = httpResponse.satisfies(expectedResponseProperties),
                    headersMatch = httpResponseMatches || httpResponse.headers.satisfy(expectedResponseProperties.headers),
                    bodyMatches = httpResponseMatches || !('body' in expectedResponseProperties) || httpResponse.satisfies({body: expectedResponseProperties.body});

                expect(context.metadata, 'to have properties', value);

                //delete expectedResponseProperties.body;
                // expect(responseProperties, 'to have properties', expectedResponseProperties);
                if (!headersMatch || !bodyMatches) {
                    // console.log(expect.inspect(httpResponse, expect.output.clone()).toString('ansi'));
                }
            } catch (assertionError) {
                err = assertionError;
            }
            setImmediate(function () {
                done(err, context);
            });
        }
        ['write', 'end', 'destroy'].forEach(function (methodName) {
            var orig = res[methodName];
            res[methodName] = function (chunk, encoding) {
                var returnValue = orig.apply(this, arguments);
                if (methodName !== 'destroy') {
                    if (encoding && !/^utf-?8$/i.test(encoding)) {
                        throw new Error('encoding parameter not supported except for "utf-8": ' + encoding);
                    }
                    if (chunk) {
                        responseBodyChunks.push(chunk);
                    }
                }
                if (methodName === 'end' || methodName === 'destroy') {
                    isDestroyed = methodName === 'destroy';
                    doTheAssertions();
                }
                return returnValue;
            };
        });
        subject(req, res, next);
    });
};
<|endoftext|>


<commit_before>const AsyncSeriesHook = require('tapable/lib/AsyncSeriesHook')
const getDebugger = require('./debug')
const isCompilerV4 = require('./isCompilerV4')

const COMPAT_PLUGINS_MAP = {
  v3: {
    'afterEnvironment': 'after-environment',
    'entryOption': 'entry-option',
    'afterPlugins': 'after-plugins',
    'afterResolvers': 'after-resolvers',
    'beforeRun': 'before-run',
    'watchRun': 'watch-run',
    'normalModuleFactory': 'normal-module-factory',
    'contextModuleFactory': 'context-module-factory',
    'beforeCompile': 'before-compile',
    'thisCompilation': 'this-compilation',
    'afterCompile': 'after-compile',
    'shouldEmit': 'should-emit',
    'needAdditionalPass': 'need-additional-pass',
    'afterEmit': 'after-emit',
    'watchClose': 'watch-close'
  },
  v4: {
    'after-environment': 'afterEnvironment',
    'entry-option': 'entryOption',
    'after-plugins': 'afterPlugins',
    'after-resolvers': 'afterResolvers',
    'before-run': 'beforeRun',
    'watch-run': 'watchRun',
    'normal-module-factory': 'normalModuleFactory',
    'context-module-factory': 'contextModuleFactory',
    'before-compile': 'beforeCompile',
    'this-compilation': 'thisCompilation',
    'after-compile': 'afterCompile',
    'should-emit': 'shouldEmit',
    'need-additional-pass': 'needAdditionalPass',
    'after-emit': 'afterEmit',
    'watch-close': 'watchClose'
  }
}

function compatPlugin(compiler, stageName, pluginName, tapMethod, plugin) {
  if (typeof tapMethod === 'function') {
    plugin = tapMethod
    tapMethod = undefined
  }

  tapMethod = tapMethod || 'tap'

  if (isCompilerV4(compiler)) {
    stageName = COMPAT_PLUGINS_MAP.v4[stageName] || stageName

    if (!(stageName in compiler.hooks)) {
      const pluginArgNames = (
        (plugin + '')
          // remove comments
          .replace(/\/\*[\s\S]*?\*\/|\/\/.*?[\r\n]/g, '')
          // match params
          .match(/\(([\s\S]*?)\)/)
        // give an empty string when no params matched
        || [0, '']
      // match names
      )[1].match(/[$\w]+/g)
      || [];

      getDebugger('udk', compiler.options.name, 'cpl')('add async series hook %o with params %o', stageName, pluginArgNames)

      compiler.hooks[stageName] = new AsyncSeriesHook(pluginArgNames)
    }

    compiler.hooks[stageName][tapMethod](pluginName, (...args) => {
      let result

      try {
        result = plugin(...args)
      } catch (err) {
        result = Promise.reject(err)
      }

      return result
    })
  } else {
    stageName = COMPAT_PLUGINS_MAP.v3[stageName] || stageName

    compiler.plugin(stageName, plugin)
  }
}

module.exports = compatPlugin<commit_msg>compatPlugin: fix undefined exception when compiler is a multi-compiler<commit_after>const AsyncSeriesHook = require('tapable/lib/AsyncSeriesHook')
const getDebugger = require('./debug')
const isCompilerV4 = require('./isCompilerV4')

const COMPAT_PLUGINS_MAP = {
  v3: {
    'afterEnvironment': 'after-environment',
    'entryOption': 'entry-option',
    'afterPlugins': 'after-plugins',
    'afterResolvers': 'after-resolvers',
    'beforeRun': 'before-run',
    'watchRun': 'watch-run',
    'normalModuleFactory': 'normal-module-factory',
    'contextModuleFactory': 'context-module-factory',
    'beforeCompile': 'before-compile',
    'thisCompilation': 'this-compilation',
    'afterCompile': 'after-compile',
    'shouldEmit': 'should-emit',
    'needAdditionalPass': 'need-additional-pass',
    'afterEmit': 'after-emit',
    'watchClose': 'watch-close'
  },
  v4: {
    'after-environment': 'afterEnvironment',
    'entry-option': 'entryOption',
    'after-plugins': 'afterPlugins',
    'after-resolvers': 'afterResolvers',
    'before-run': 'beforeRun',
    'watch-run': 'watchRun',
    'normal-module-factory': 'normalModuleFactory',
    'context-module-factory': 'contextModuleFactory',
    'before-compile': 'beforeCompile',
    'this-compilation': 'thisCompilation',
    'after-compile': 'afterCompile',
    'should-emit': 'shouldEmit',
    'need-additional-pass': 'needAdditionalPass',
    'after-emit': 'afterEmit',
    'watch-close': 'watchClose'
  }
}

function compatPlugin(compiler, stageName, pluginName, tapMethod, plugin) {
  if (typeof tapMethod === 'function') {
    plugin = tapMethod
    tapMethod = undefined
  }

  tapMethod = tapMethod || 'tap'

  if (isCompilerV4(compiler)) {
    stageName = COMPAT_PLUGINS_MAP.v4[stageName] || stageName

    if (!(stageName in compiler.hooks)) {
      const pluginArgNames = (
        (plugin + '')
          // remove comments
          .replace(/\/\*[\s\S]*?\*\/|\/\/.*?[\r\n]/g, '')
          // match params
          .match(/\(([\s\S]*?)\)/)
        // give an empty string when no params matched
        || [0, '']
      // match names
      )[1].match(/[$\w]+/g)
      || [];

      const compilerName = compiler.compilers
        ? 'multi'
        : compiler.options.name

      getDebugger('udk', compilerName, 'cpl')('add async series hook %o with params %o', stageName, pluginArgNames)

      compiler.hooks[stageName] = new AsyncSeriesHook(pluginArgNames)
    }

    compiler.hooks[stageName][tapMethod](pluginName, (...args) => {
      let result

      try {
        result = plugin(...args)
      } catch (err) {
        result = Promise.reject(err)
      }

      return result
    })
  } else {
    stageName = COMPAT_PLUGINS_MAP.v3[stageName] || stageName

    compiler.plugin(stageName, plugin)
  }
}

module.exports = compatPlugin<|endoftext|>


<commit_before>/**
 * @fileOverview This test specs runs tests on the package.json file of repository. It has a set of strict tests on the
 * content of the file as well. Any change to package.json must be accompanied by valid test case in this spec-sheet.
 */
var _ = require('lodash'),
    yml = require('js-yaml'),
    parseIgnore = require('parse-gitignore'),
    expect = require('chai').expect,
    fs = require('fs');

describe('project repository', function () {
    describe('package.json', function () {
        var content,
            json;

        try {
            content = fs.readFileSync('./package.json').toString();
            json = JSON.parse(content);
        }
        catch (e) { } // eslint-disable-line no-empty

        it('should exist', function (done) {
            fs.stat('./package.json', done);
        });

        it('should have readable content', function () {
            expect(content, 'Should have readable content').to.be.a('string');
        });

        it('should have valid JSON content', function () {
            expect(json, 'Should have valid JSON content').to.be.an('object');
        });

        describe('package.json JSON data', function () {
            it('should have valid name, description, author and license', function () {
                expect(json).to.deep.include({
                    name: 'postman-sandbox',
                    description: 'Sandbox for Postman Scripts to run in NodeJS or Chrome',
                    author: 'Postman Inc.',
                    license: 'Apache-2.0'
                });
            });

            it('should have a valid version string in form of <major>.<minor>.<revision>', function () {
                expect(json.version)
                    // eslint-disable-next-line max-len, security/detect-unsafe-regex
                    .to.match(/^((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$/);
            });

            // @note updating csv-parse will break postman script because of breaking
            // API and options changes introduced in csv-parse
            it('should have dev dependency csv-parse v1.2.4', function () {
                expect(json.devDependencies).to.have.property('csv-parse', '1.2.4');
            });

            // @note crypto-js v4 uses native crypto module which will not work after browserify
            it('should have dev dependency crypto-js v3.3.0', function () {
                expect(json.devDependencies).to.have.property('crypto-js', '3.3.0');
            });

            // @note use same tough-cookie version as in postman-request and postman-runtime
            it('should have dev dependency tough-cookie v3.0.1', function () {
                expect(json.devDependencies).to.have.property('tough-cookie', '3.0.1');
            });
        });

        describe('devDependencies', function () {
            it('should exist', function () {
                expect(json.devDependencies).to.be.an('object');
            });

            it('should point to a valid semver', function () {
                Object.keys(json.devDependencies).forEach(function (dependencyName) {
                    // eslint-disable-next-line security/detect-non-literal-regexp
                    expect(json.devDependencies[dependencyName]).to.match(new RegExp('((\\d+)\\.(\\d+)\\.(\\d+))(?:-' +
                        '([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?(?:\\+([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?$'));
                });
            });
        });

        describe('main entry script', function () {
            it('should point to a valid file', function (done) {
                expect(json.main).to.equal('index.js');
                fs.stat(json.main, done);
            });
        });
    });

    describe('README.md', function () {
        it('should exist', function (done) {
            fs.stat('./README.md', done);
        });

        it('should have readable content', function () {
            expect(fs.readFileSync('./README.md').toString()).to.be.ok;
        });
    });

    describe('LICENSE.md', function () {
        it('should exist', function (done) {
            fs.stat('./LICENSE.md', done);
        });

        it('should have readable content', function () {
            expect(fs.readFileSync('./LICENSE.md').toString()).to.be.ok;
        });
    });

    describe('.gitattributes', function () {
        it('should exist', function (done) {
            fs.stat('./.gitattributes', done);
        });

        it('should have readable content', function () {
            expect(fs.readFileSync('./.gitattributes').toString()).to.be.ok;
        });
    });

    describe('CHANGELOG.yaml', function () {
        it('should exist', function (done) {
            fs.stat('./CHANGELOG.yaml', done);
        });

        it('should have readable content', function () {
            expect(yml.safeLoad(fs.readFileSync('./CHANGELOG.yaml')), 'not a valid yaml').to.be.ok;
        });
    });

    describe('.ignore files', function () {
        var gitignorePath = '.gitignore',
            npmignorePath = '.npmignore',
            npmignore = parseIgnore(fs.readFileSync(npmignorePath)),
            gitignore = parseIgnore(fs.readFileSync(gitignorePath));

        describe(gitignorePath, function () {
            it('should exist', function (done) {
                fs.stat(gitignorePath, done);
            });

            it('should have valid content', function () {
                expect(gitignore).to.not.be.empty;
            });

            it('should not ignore the .cache directory', function () {
                expect(gitignore).to.include.members(['.cache']);
            });
        });

        describe(npmignorePath, function () {
            it('should exist', function (done) {
                fs.stat(npmignorePath, done);
            });

            it('should have valid content', function () {
                expect(gitignore).to.not.be.empty;
            });

            it('should not ignore the .cache directory', function () {
                expect(npmignore).to.not.include('**/.cache');
                expect(npmignore).to.not.include('**/.cache/**');
            });
        });

        it('.gitignore coverage must be a subset of .npmignore coverage (except .cache directory)', function () {
            expect(_.intersection(gitignore, _.union(npmignore, ['.cache']))).to.eql(gitignore);
        });
    });
});
<commit_msg>Test: update description in package.json<commit_after>/**
 * @fileOverview This test specs runs tests on the package.json file of repository. It has a set of strict tests on the
 * content of the file as well. Any change to package.json must be accompanied by valid test case in this spec-sheet.
 */
var _ = require('lodash'),
    yml = require('js-yaml'),
    parseIgnore = require('parse-gitignore'),
    expect = require('chai').expect,
    fs = require('fs');

describe('project repository', function () {
    describe('package.json', function () {
        var content,
            json;

        try {
            content = fs.readFileSync('./package.json').toString();
            json = JSON.parse(content);
        }
        catch (e) { } // eslint-disable-line no-empty

        it('should exist', function (done) {
            fs.stat('./package.json', done);
        });

        it('should have readable content', function () {
            expect(content, 'Should have readable content').to.be.a('string');
        });

        it('should have valid JSON content', function () {
            expect(json, 'Should have valid JSON content').to.be.an('object');
        });

        describe('package.json JSON data', function () {
            it('should have valid name, description, author and license', function () {
                expect(json).to.deep.include({
                    name: 'postman-sandbox',
                    description: 'Sandbox for Postman Scripts to run in Node.js or browser',
                    author: 'Postman Inc.',
                    license: 'Apache-2.0'
                });
            });

            it('should have a valid version string in form of <major>.<minor>.<revision>', function () {
                expect(json.version)
                    // eslint-disable-next-line max-len, security/detect-unsafe-regex
                    .to.match(/^((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$/);
            });

            // @note updating csv-parse will break postman script because of breaking
            // API and options changes introduced in csv-parse
            it('should have dev dependency csv-parse v1.2.4', function () {
                expect(json.devDependencies).to.have.property('csv-parse', '1.2.4');
            });

            // @note crypto-js v4 uses native crypto module which will not work after browserify
            it('should have dev dependency crypto-js v3.3.0', function () {
                expect(json.devDependencies).to.have.property('crypto-js', '3.3.0');
            });

            // @note use same tough-cookie version as in postman-request and postman-runtime
            it('should have dev dependency tough-cookie v3.0.1', function () {
                expect(json.devDependencies).to.have.property('tough-cookie', '3.0.1');
            });
        });

        describe('devDependencies', function () {
            it('should exist', function () {
                expect(json.devDependencies).to.be.an('object');
            });

            it('should point to a valid semver', function () {
                Object.keys(json.devDependencies).forEach(function (dependencyName) {
                    // eslint-disable-next-line security/detect-non-literal-regexp
                    expect(json.devDependencies[dependencyName]).to.match(new RegExp('((\\d+)\\.(\\d+)\\.(\\d+))(?:-' +
                        '([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?(?:\\+([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?$'));
                });
            });
        });

        describe('main entry script', function () {
            it('should point to a valid file', function (done) {
                expect(json.main).to.equal('index.js');
                fs.stat(json.main, done);
            });
        });
    });

    describe('README.md', function () {
        it('should exist', function (done) {
            fs.stat('./README.md', done);
        });

        it('should have readable content', function () {
            expect(fs.readFileSync('./README.md').toString()).to.be.ok;
        });
    });

    describe('LICENSE.md', function () {
        it('should exist', function (done) {
            fs.stat('./LICENSE.md', done);
        });

        it('should have readable content', function () {
            expect(fs.readFileSync('./LICENSE.md').toString()).to.be.ok;
        });
    });

    describe('.gitattributes', function () {
        it('should exist', function (done) {
            fs.stat('./.gitattributes', done);
        });

        it('should have readable content', function () {
            expect(fs.readFileSync('./.gitattributes').toString()).to.be.ok;
        });
    });

    describe('CHANGELOG.yaml', function () {
        it('should exist', function (done) {
            fs.stat('./CHANGELOG.yaml', done);
        });

        it('should have readable content', function () {
            expect(yml.safeLoad(fs.readFileSync('./CHANGELOG.yaml')), 'not a valid yaml').to.be.ok;
        });
    });

    describe('.ignore files', function () {
        var gitignorePath = '.gitignore',
            npmignorePath = '.npmignore',
            npmignore = parseIgnore(fs.readFileSync(npmignorePath)),
            gitignore = parseIgnore(fs.readFileSync(gitignorePath));

        describe(gitignorePath, function () {
            it('should exist', function (done) {
                fs.stat(gitignorePath, done);
            });

            it('should have valid content', function () {
                expect(gitignore).to.not.be.empty;
            });

            it('should not ignore the .cache directory', function () {
                expect(gitignore).to.include.members(['.cache']);
            });
        });

        describe(npmignorePath, function () {
            it('should exist', function (done) {
                fs.stat(npmignorePath, done);
            });

            it('should have valid content', function () {
                expect(gitignore).to.not.be.empty;
            });

            it('should not ignore the .cache directory', function () {
                expect(npmignore).to.not.include('**/.cache');
                expect(npmignore).to.not.include('**/.cache/**');
            });
        });

        it('.gitignore coverage must be a subset of .npmignore coverage (except .cache directory)', function () {
            expect(_.intersection(gitignore, _.union(npmignore, ['.cache']))).to.eql(gitignore);
        });
    });
});
<|endoftext|>


<commit_before>'use strict'

const crypto = require('crypto')
let nonce = Date.now()

const genAuthSig = (secret, payload = '') => {
  if (payload.length === 0) {
    payload = `AUTH${nonce}${nonce}`
  }

  const sig = crypto
    .createHmac('sha384', secret)
    .update(payload)
    .digest('hex')

  return {
    payload,
    sig,
    nonce: nonce++
  }
}

module.exports = genAuthSig
<commit_msg>(fix) nonce * 1000 in gen_auth_sig<commit_after>'use strict'

const crypto = require('crypto')
let nonce = Date.now() * 1000

const genAuthSig = (secret, payload = '') => {
  if (payload.length === 0) {
    payload = `AUTH${nonce}${nonce}`
  }

  const sig = crypto
    .createHmac('sha384', secret)
    .update(payload)
    .digest('hex')

  return {
    payload,
    sig,
    nonce: nonce++
  }
}

module.exports = genAuthSig
<|endoftext|>


<commit_before>/** @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

goog.provide('shaka.util.IReleasable');

/**
 * An interface to standardize how objects release internal references
 * synchronously. If an object needs to asynchronously release references, then
 * it should use 'shaka.util.IDestroyable'.
 *
 * @interface
 * @export
 */
shaka.util.IReleasable = class {
  /**
   * Request that this object release all internal references.
   *
   * @exportInterface
   */
  release() {}
};
<commit_msg>Fix export annotation on abstract IReleasable<commit_after>/** @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

goog.provide('shaka.util.IReleasable');

/**
 * An interface to standardize how objects release internal references
 * synchronously. If an object needs to asynchronously release references, then
 * it should use 'shaka.util.IDestroyable'.
 *
 * @interface
 * @exportInterface
 */
shaka.util.IReleasable = class {
  /**
   * Request that this object release all internal references.
   *
   * @exportInterface
   */
  release() {}
};
<|endoftext|>