<commit_before>// Load the fs (filesystem) module
var fs = require("fs");
var https = require("https");
var underscore = require("underscore");
var async = require("async");

function getPerson(cb) {
    fs.readFile("example_person.json", "utf8", function (err,data){
        var person = JSON.parse(data);
        cb(null, person.person);
    });
}

function getAngelData(path, cb) {
    var url;
    if (path !== null) {
        url = "https://api.angel.co/1/" + path;
    }else{
        url = "https://api.angel.co/1/jobs";
    }

    https.get(url, function(res) {
        var body = '';
        res.on('data', function(chunk) {
            body += chunk;
        });

        res.on('end', function() {
            var angellist = JSON.parse(body);
            cb(null, angellist);
        });
    }).on('error', function(e) {
          console.log("Got error: ", e);
    });
}

function checkForMultiple(job_field, role, cb){ // Given a json field that returns array check for all array elements in string
    var rank = 0;
    for (var i in role){
        if (job_field !== null){
            if(job_field.toLowerCase().indexOf(role[i].toLowerCase()) > -1 ) {
                rank++;
            }
        }
    }
    return rank;
}

function findViableJobs(jobs, person, cb){
    var viable_job = [];
    var job_rank;
    jobs.forEach(function(job){
        if (job.job_type == person.job_type){
            job_rank = checkForMultiple(job.title, person.role) + checkForMultiple(job.description, person.stack);
            if(job_rank > 0){
                viable_job.push([job_rank, job.id]);
            }
        }
    });
    return viable_job;
}

//Load AngelList API and Get Person.
getPerson(function (err,person) {

    var location_queries = [];

    person.location_desired.forEach(function(location_desired){ // Build Location Paths
        location_queries.push("search?query=" + location_desired + "&type=LocationTag");
    });

    async.map(location_queries, getAngelData.bind(null), function(err, data){ // Get Location IDs
        var locations = underscore.flatten(data, true);
        var location_path = [];

        locations.forEach(function(location){ // Build search paths based on location
            location_path.push("tags/" + location.id + "/jobs");
        });

        async.map(location_path, getAngelData.bind(null), function(err, data){ // Get jobs

            var jobs = underscore.flatten(data, true);
            jobs = underscore.pluck(jobs, "jobs");
            jobs = underscore.flatten(jobs, true);

            var viable_job = findViableJobs(jobs, person); // Check Jobs for viability based on user set criteria
            viable_job = viable_job.sort(function(a, b){return b[0]-a[0];});

            for (var s = 0; s < 10; s++){
                console.log(viable_job[s]);
            }
        });
    });

    // getAngelData('/32886', function(err,data){
    //     console.log(data);
    // });
} );
<commit_msg>Altered Ranking System. Limited Output by 10<commit_after>// Load the fs (filesystem) module
var fs = require("fs");
var https = require("https");
var underscore = require("underscore");
var async = require("async");

function getPerson(cb) {
    fs.readFile("example_person.json", "utf8", function (err,data){
        var person = JSON.parse(data);
        cb(null, person.person);
    });
}

function getAngelData(path, cb) {
    var url;
    if (path !== null) {
        url = "https://api.angel.co/1/" + path;
    }else{
        url = "https://api.angel.co/1/jobs";
    }

    https.get(url, function(res) {
        var body = '';
        res.on('data', function(chunk) {
            body += chunk;
        });

        res.on('end', function() {
            var angellist = JSON.parse(body);
            cb(null, angellist);
        });
    }).on('error', function(e) {
          console.log("Got error: ", e);
    });
}

function checkForMultiple(job_field, role, cb){ // Given a json field that returns array check for all array elements in string
    var rank = 0;
    for (var i in role){
        if (job_field !== null){
            if(job_field.toLowerCase().indexOf(role[i].toLowerCase()) > -1 ) {
                rank++;
            }
        }
    }
    return rank;
}

function findViableJobs(jobs, person, cb){
    var viable_job = [];
    var job_rank;
    jobs.forEach(function(job){
        if (job.job_type == person.job_type){
            job_rank = checkForMultiple(job.title, person.role) + checkForMultiple(job.description, person.stack);
            if(job_rank > 0){
                viable_job.push([job_rank, job.id]);
            }
        }
    });
    return viable_job;
}

//Load AngelList API and Get Person.
getPerson(function (err,person) {

    var location_queries = [];

    person.location_desired.forEach(function(location_desired){ // Build Location Paths
        location_queries.push("search?query=" + location_desired + "&type=LocationTag");
    });

    async.map(location_queries, getAngelData.bind(null), function(err, data){ // Get Location IDs
        var locations = underscore.flatten(data, true);
        var location_path = [];

        locations.forEach(function(location){ // Build search paths based on location
            location_path.push("tags/" + location.id + "/jobs");
        });

        async.map(location_path, getAngelData.bind(null), function(err, data){ // Get jobs

            var jobs = underscore.flatten(data, true);
            jobs = underscore.pluck(jobs, "jobs");
            jobs = underscore.flatten(jobs, true);

            var viable_job = findViableJobs(jobs, person); // Check Jobs for viability based on user set criteria
            viable_job = viable_job.sort(function(a, b){return b[0]-a[0];});

            var output_len =10;

            if (viable_job.length < output_len){
                output_len = viable_job.length;
            }

            for (var s = 0; s < output_len; s++){
                console.log(viable_job[s]);
            }
        });
    });

    // getAngelData('/32886', function(err,data){
    //     console.log(data);
    // });
} );
<|endoftext|>


<commit_before>/*

Title: imageFileToCroppedImageFiles.js
Original creator: Leonard Pauli
Date: 18/3-2015
License: MIT

Functions:

aspectContainImageCrop(image, size, isPng) -> Image
imageFileToCroppedImageFiles(file, sizes, callback) (files)

getImageFromSrc(src, callback) (image)
getImageFromFile(file, callback) (image)

dataURItoBlob(dataURI) -> Blob

*/

function aspectContainImageCrop(image, size, isPng) {

  // Only possibly necessary for remote images to prevent
  // x-origin error (lookup if it's needed at all)
  image.crossOrigin='anonymous'

  // Get a canvas to draw on
  var canvas = document.createElement('canvas');
  var ctx = canvas.getContext('2d');

  // Figure out if the image has transparancy
  isPng = isPng | (function (ctx, canvas, image) {
    canvas.setAttribute('width', image.width/3);
    canvas.setAttribute('height', image.height/3);

    ctx.drawImage(image, 0, 0, canvas.width, canvas.height);

    var imgData = ctx.getImageData(0,0,canvas.width,canvas.height).data;
    var isTrans = false;
    for (var i = 3; i<imgData.length; i+=4)
      if (imgData[i]<255) {
        isTrans = true;
        break;
      }

    return isTrans;
  })(ctx, canvas, image);

  // Get smallest source/destination size factor
  var scale = (isPng?Math.min:Math.max)(image.width/size.w, image.height/size.h);

  // Scale destination so that smallest
  // side matches smallest source side
  var toSize = {
    w:size.w*scale,
    h:size.h*scale
  };

  // Final can be smaller than or equal destination
  var imageScale = Math.min(1,size.w/toSize.w);

  // If final smaller than source,
  // cut overflow to center image
  var cutStart = {
    x:(image.width-toSize.w)/2,
    y:(image.height-toSize.h)/2
  };
  console.log(imageScale, toSize);

  // Reset the canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  canvas.setAttribute('width', toSize.w*imageScale);
  canvas.setAttribute('height', toSize.h*imageScale);

  // Cut and resize image by drawing it scaled in a frame
  ctx.drawImage(image, cutStart.x, cutStart.y, toSize.w, toSize.h, 0, 0, toSize.w*imageScale, toSize.h*imageScale);

  // Convert image to data
  var base64ImageData;
  if (isPng) base64ImageData = canvas.toDataURL("image/png");
  else base64ImageData = canvas.toDataURL("image/jpeg", 0.8);

  // Clean up
  //canvas.parent().removeChild(canvas);

  return base64ImageData;
}

window.getImageFromSrc = function(src, callback) {
  if (!src) return callback();

  var image = new Image();
  image.onload = function() {
    callback(image);
  }
  image.src = src;
}

window.getImageFromFile = function(file, callback) {
  if (!file) return callback();

  var image = new Image();
  image.onload = function() {
    callback(image);
    URL.revokeObjectURL(image.src)
  }
  image.src = URL.createObjectURL(file);
}

window.dataURItoBlob = function(dataURI) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
    else
        byteString = unescape(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    return new Blob([ia], {type:mimeString});
}

window.imageFileToCroppedImageFiles = function(file, sizes, callback) {
  var isPng = file.type==="image/png";
  getImageFromFile(file, function (original) {
    if (!original) return callback();

    var files = [];
    for (var i = 0; i<sizes.length; i++)
      files[files.length] = dataURItoBlob(aspectContainImageCrop(original, sizes[i], isPng));

    return callback(files);
  });
}<commit_msg>Fixed a typo that inverted cover/contain selection<commit_after>/*

Title: imageFileToCroppedImageFiles.js
Original creator: Leonard Pauli
Date: 18/3-2015
License: MIT

Functions:

aspectContainImageCrop(image, size, isPng) -> Image
imageFileToCroppedImageFiles(file, sizes, callback) (files)

getImageFromSrc(src, callback) (image)
getImageFromFile(file, callback) (image)

dataURItoBlob(dataURI) -> Blob

*/

function aspectContainImageCrop(image, size, isPng) {

  // Only possibly necessary for remote images to prevent
  // x-origin error (lookup if it's needed at all)
  image.crossOrigin='anonymous'

  // Get a canvas to draw on
  var canvas = document.createElement('canvas');
  var ctx = canvas.getContext('2d');

  // Figure out if the image has transparancy
  isPng = isPng | (function (ctx, canvas, image) {
    canvas.setAttribute('width', image.width/3);
    canvas.setAttribute('height', image.height/3);

    ctx.drawImage(image, 0, 0, canvas.width, canvas.height);

    var imgData = ctx.getImageData(0,0,canvas.width,canvas.height).data;
    var isTrans = false;
    for (var i = 3; i<imgData.length; i+=4)
      if (imgData[i]<255) {
        isTrans = true;
        break;
      }

    return isTrans;
  })(ctx, canvas, image);

  // Get smallest source/destination size factor
  var scale = (isPng?Math.max:Math.min)(image.width/size.w, image.height/size.h);

  // Scale destination so that smallest
  // side matches smallest source side
  var toSize = {
    w:size.w*scale,
    h:size.h*scale
  };

  // Final can be smaller than or equal destination
  var imageScale = Math.min(1,size.w/toSize.w);

  // If final smaller than source,
  // cut overflow to center image
  var cutStart = {
    x:(image.width-toSize.w)/2,
    y:(image.height-toSize.h)/2
  };
  console.log(imageScale, toSize);

  // Reset the canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  canvas.setAttribute('width', toSize.w*imageScale);
  canvas.setAttribute('height', toSize.h*imageScale);

  // Cut and resize image by drawing it scaled in a frame
  ctx.drawImage(image, cutStart.x, cutStart.y, toSize.w, toSize.h, 0, 0, toSize.w*imageScale, toSize.h*imageScale);

  // Convert image to data
  var base64ImageData;
  if (isPng) base64ImageData = canvas.toDataURL("image/png");
  else base64ImageData = canvas.toDataURL("image/jpeg", 0.8);

  // Clean up
  //canvas.parent().removeChild(canvas);

  return base64ImageData;
}

window.getImageFromSrc = function(src, callback) {
  if (!src) return callback();

  var image = new Image();
  image.onload = function() {
    callback(image);
  }
  image.src = src;
}

window.getImageFromFile = function(file, callback) {
  if (!file) return callback();

  var image = new Image();
  image.onload = function() {
    callback(image);
    URL.revokeObjectURL(image.src)
  }
  image.src = URL.createObjectURL(file);
}

window.dataURItoBlob = function(dataURI) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
    else
        byteString = unescape(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    return new Blob([ia], {type:mimeString});
}

window.imageFileToCroppedImageFiles = function(file, sizes, callback) {
  var isPng = file.type==="image/png";
  getImageFromFile(file, function (original) {
    if (!original) return callback();

    var files = [];
    for (var i = 0; i<sizes.length; i++)
      files[files.length] = dataURItoBlob(aspectContainImageCrop(original, sizes[i], isPng));

    return callback(files);
  });
}<|endoftext|>


<commit_before>/**
 * @fileOverview tests.js Gives testing code for the Chrome Extension.
 * It is currently being used to develope new functionality, but test
 * cases will be added for complete code coverage. It recently changed
 * to the Jasmine JS testing library, but full integration is not complete.
 * Notably, the testing style is not following Jasmine's conventions on
 * "wait."
 **/

describe("Extension", function() {

  beforeEach(function() {
    //pass
  });

  /**
   * Tests modal button functionality. This is a naively implemented
   * test case. Future versions should more gracefully handle Chrome's
   * callbacks. This example indicates that every function may need to
   * support a callback parameter in order to support asynchronous testing.
   */
  it("should change the modal button", function() {

    //Get all the windows so we can get a tab
    chrome.windows.getAll({"populate" : true},
      function(windows){

        // Get a valid Tab
        var tab = null;
        for (var i = 0; i < windows.length; i++) {
          if(windows[i].tabs.length > 0) {
            tab = windows[i].tabs[0];
          }
        }

        // Get the current setting of the badge text
        // so we can flip it.
        chrome.browserAction.getBadgeText({},
          function(currentText) {

            // We define a callback for the function we are testing so we can
            // check the results without needing to use setTimeout
            function testingCallback() {
              if (currentText === "off") {
                chrome.browserAction.getBadgeText({},
                  function(currentText) {
                    expect(currentText).toEqual("on");
                  }
                );
              } else if(currentText === "on") {
                chrome.browserAction.getBadgeText({},
                  function(currentText) {
                    expect(currentText).toEqual("off");
                  }
                );
              } else {
                expect("false").toEqual("true");
              }

              // Attempt to toggle the modal button back to its prior state
              modalButtonCallback(tab);
            }

            // Now that we have setup the test, it is time to check the
            modalButtonCallback(tab, testingCallback);
          }
        );
      }
    );
  });
});
describe ("First Run Suite", function() {
    /*
        Test the function that gets the running privly version
    */
    it("tests getPrivlyVersion", function() {
        var output = getPrivlyVersion();
        expect(output).toMatch(/\d+\.\d+\.\d+/);
    });
    /*
        Test the function that gets the version in local storage
    */
    it("tests getStoredVersion", function() {
        var output = getStoredVersion();
        expect(output).toEqual(localStorage["version"]);
    });
    /*
        Test the function that updates local storage with the running version
    */
    it("tests update_version", function() {
        var existing = getStoredVersion();
        var modified = existing+"99"
        update_version(modified);
        expect(getStoredVersion()).toEqual(modified);
        update_version(existing);
    });
    /*
        Test the function that launches the first_run.html page
    */
    it("tests firstrun", function(){
      //Get the url of the first_run.html
      var page = chrome.extension.getURL("pages/first_run.html");
      var Window = 0;
      //Look at all windows
      chrome.windows.getAll({populate:true},function(window_list){
        var count_before = 0;
        var nope = 0;
        for (var i = 0; i < window_list.length; i++){
          //return all tabs in each window that match the first_run url
          chrome.tabs.query({windowId:parseInt(window_list[i].id,10),url:page},function(tab){
            count_before+=1
          });
          waits(500);
          //if on the last window
         if (i === window_list.length-1){
            //load new window
            firstrun();
            var count_after = 0;
            //Look at all windows
            chrome.windows.getAll({populate:true},function(win_list){
              for(var i = 0; i < win_list.length; i++){
                //return all tabs in each window that match the first_run url
                chrome.tabs.query({windowId:parseInt(win_list[i].id,10),url:page},function(tab){
                  count_after+=1;
                });
                waits(500);
                if ( i === win_list.length-1){
                    expect(count_after).toEqual(count_before+1);
                }
              }
            });
          }
        }
      });
    });
    /*
        Test the function that launches the first_run.html page when not updated or new
    */
    it("tests run_firstrun when not new", function() {
      var page = chrome.extension.getURL("pages/first_run.html");
      var stored = getStoredVersion();
      var running = getPrivlyVersion();
      var tabs_before = 0;
      chrome.windows.getAll({populate:true},function(win_list){
        for(var i = 0; i < win_list.length; i++){
          chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
            tabs_before+= tab.length;
          });
          waits(500);
          if (i === win_list.length-1 && stored === running){
            run_firstrun();
            var tabs_after = 0;
            chrome.windows.getAll({populate:true},function(wind_list){
              for (var i = 0; i < wind_list.length; i++){
                chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
                  tabs_after += tab.length;
                });
                waits(500);
                if (i === wind_list.length-1){
                  expect(tabs.length).toEqual(tabs_after.length);
                }
              }
            });
          } else {
            expect(1).toEqual(1);
          }
        }
      });
    });
    it("tests run_firstrun when new", function() {
    /*
        Test the function that launches the first_run.html page when new
    */
      var page = chrome.extension.getURL("pages/first_run.html");
      var stored = getStoredVersion();
      var running = getPrivlyVersion();
      var tabs_before = 0;
      chrome.windows.getAll({populate:true},function(win_list){
        for(var i = 0; i < win_list.length; i++){
          chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
            tabs_before+= tab.length;
          });
          waits(500);
          if (i === win_list.length-1){
            update_version(null);
            run_firstrun();
            update_version(stored);
            var tabs_after = 0;
            chrome.windows.getAll({populate:true},function(wind_list){
              for (var i = 0; i < wind_list.length; i++){
                chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
                  tabs_after += tab.length;
                });
                waits(500);
                if (i === wind_list.length-1){
                  expect(tabs.length).toEqual(tabs_after.length+1);
                }
              }
            });
          } else {
            expect(1).toEqual(1);
          }
        }
      });
    });
    /*
        Test the function that launches the first_run.html page when updated
    */
    it("tests run_firstrun when updated", function() {
      var page = chrome.extension.getURL("pages/first_run.html");
      var stored = getStoredVersion();
      var running = getPrivlyVersion();
      var tabs_before = 0;
      chrome.windows.getAll({populate:true},function(win_list){
        for(var i = 0; i < win_list.length; i++){
          chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
            tabs_before+= tab.length;
          });
          waits(500);
          if (i === win_list.length-1){
            //modify version in local storage
            update_version(stored+"99");
            run_firstrun();
            //reset version to original
            update_version(stored);
            var tabs_after = 0;
            chrome.windows.getAll({populate:true},function(wind_list){
              for (var i = 0; i < wind_list.length; i++){
                chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
                  tabs_after += tab.length;
                });
                waits(500);
                if (i === wind_list.length-1){
                  expect(tabs.length).toEqual(tabs_after.length+1);
                }
              }
            });
          } else {
            expect(1).toEqual(1);
          }
        }
      });
    });
});

(function() {
  var jasmineEnv = jasmine.getEnv();
  jasmineEnv.updateInterval = 1000;

  var htmlReporter = new jasmine.HtmlReporter();

  jasmineEnv.addReporter(htmlReporter);

  jasmineEnv.specFilter = function(spec) {
    return htmlReporter.specFilter(spec);
  };

  var currentWindowOnload = window.onload;

  window.onload = function() {
    if (currentWindowOnload) {
      currentWindowOnload();
    }
    execJasmine();
  };

  function execJasmine() {
    jasmineEnv.execute();
  }

})();

<commit_msg>Modified comments to adhere to style guide.<commit_after>/**
 * @fileOverview tests.js Gives testing code for the Chrome Extension.
 * It is currently being used to develope new functionality, but test
 * cases will be added for complete code coverage. It recently changed
 * to the Jasmine JS testing library, but full integration is not complete.
 * Notably, the testing style is not following Jasmine's conventions on
 * "wait."
 **/

describe("Extension", function() {

  beforeEach(function() {
    //pass
  });

  /**
   * Tests modal button functionality. This is a naively implemented
   * test case. Future versions should more gracefully handle Chrome's
   * callbacks. This example indicates that every function may need to
   * support a callback parameter in order to support asynchronous testing.
   */
  it("should change the modal button", function() {

    //Get all the windows so we can get a tab
    chrome.windows.getAll({"populate" : true},
      function(windows){

        // Get a valid Tab
        var tab = null;
        for (var i = 0; i < windows.length; i++) {
          if(windows[i].tabs.length > 0) {
            tab = windows[i].tabs[0];
          }
        }

        // Get the current setting of the badge text
        // so we can flip it.
        chrome.browserAction.getBadgeText({},
          function(currentText) {

            // We define a callback for the function we are testing so we can
            // check the results without needing to use setTimeout
            function testingCallback() {
              if (currentText === "off") {
                chrome.browserAction.getBadgeText({},
                  function(currentText) {
                    expect(currentText).toEqual("on");
                  }
                );
              } else if(currentText === "on") {
                chrome.browserAction.getBadgeText({},
                  function(currentText) {
                    expect(currentText).toEqual("off");
                  }
                );
              } else {
                expect("false").toEqual("true");
              }

              // Attempt to toggle the modal button back to its prior state
              modalButtonCallback(tab);
            }

            // Now that we have setup the test, it is time to check the
            modalButtonCallback(tab, testingCallback);
          }
        );
      }
    );
  });
});
describe ("First Run Suite", function() {

    /*
     * Test the function that gets the running privly version
     */
    it("tests getPrivlyVersion", function() {
        var output = getPrivlyVersion();
        expect(output).toMatch(/\d+\.\d+\.\d+/);
    });

    /*
     * Test the function that gets the version in local storage
     */
    it("tests getStoredVersion", function() {
        var output = getStoredVersion();
        expect(output).toEqual(localStorage["version"]);
    });

    /*
     * Test the function that updates local storage with the running version
     */
    it("tests update_version", function() {
        var existing = getStoredVersion();
        var modified = existing + "99";
        update_version(modified);
        expect(getStoredVersion()).toEqual(modified);
        update_version(existing);
    });

    /*
     * Test the function that launches the first_run.html page
     */
    it("tests firstrun", function(){
      //Get the url of the first_run.html
      var page = chrome.extension.getURL("pages/first_run.html");
      var Window = 0;
      //Look at all windows
      chrome.windows.getAll({populate:true},function(window_list){
        var count_before = 0;
        var nope = 0;
        for (var i = 0; i < window_list.length; i++){
          //return all tabs in each window that match the first_run url
          chrome.tabs.query({windowId:parseInt(window_list[i].id,10),url:page},function(tab){
            count_before+=1
          });
          waits(500);
          //if on the last window
         if (i === window_list.length-1){
            //load new window
            firstrun();
            var count_after = 0;
            //Look at all windows
            chrome.windows.getAll({populate:true},function(win_list){
              for(var i = 0; i < win_list.length; i++){
                //return all tabs in each window that match the first_run url
                chrome.tabs.query({windowId:parseInt(win_list[i].id,10),url:page},function(tab){
                  count_after+=1;
                });
                waits(500);
                if ( i === win_list.length-1){
                    expect(count_after).toEqual(count_before+1);
                }
              }
            });
          }
        }
      });
    });

    /*
     * Test the function that launches the first_run.html page when not updated or new
     */
    it("tests run_firstrun when not new", function() {
      var page = chrome.extension.getURL("pages/first_run.html");
      var stored = getStoredVersion();
      var running = getPrivlyVersion();
      var tabs_before = 0;
      chrome.windows.getAll({populate:true},function(win_list){
        for(var i = 0; i < win_list.length; i++){
          chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
            tabs_before+= tab.length;
          });
          waits(500);
          if (i === win_list.length-1 && stored === running){
            run_firstrun();
            var tabs_after = 0;
            chrome.windows.getAll({populate:true},function(wind_list){
              for (var i = 0; i < wind_list.length; i++){
                chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
                  tabs_after += tab.length;
                });
                waits(500);
                if (i === wind_list.length-1){
                  expect(tabs.length).toEqual(tabs_after.length);
                }
              }
            });
          } else {
            expect(1).toEqual(1);
          }
        }
      });
    });

    /*
     * Test the function that launches the first_run.html page when new
     */
    it("tests run_firstrun when new", function() {
      var page = chrome.extension.getURL("pages/first_run.html");
      var stored = getStoredVersion();
      var running = getPrivlyVersion();
      var tabs_before = 0;
      chrome.windows.getAll({populate:true},function(win_list){
        for(var i = 0; i < win_list.length; i++){
          chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
            tabs_before+= tab.length;
          });
          waits(500);
          if (i === win_list.length-1){
            update_version(null);
            run_firstrun();
            update_version(stored);
            var tabs_after = 0;
            chrome.windows.getAll({populate:true},function(wind_list){
              for (var i = 0; i < wind_list.length; i++){
                chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
                  tabs_after += tab.length;
                });
                waits(500);
                if (i === wind_list.length-1){
                  expect(tabs.length).toEqual(tabs_after.length+1);
                }
              }
            });
          } else {
            expect(1).toEqual(1);
          }
        }
      });
    });

    /*
     * Test the function that launches the first_run.html page when updated
     */
    it("tests run_firstrun when updated", function() {
      var page = chrome.extension.getURL("pages/first_run.html");
      var stored = getStoredVersion();
      var running = getPrivlyVersion();
      var tabs_before = 0;
      chrome.windows.getAll({populate:true},function(win_list){
        for(var i = 0; i < win_list.length; i++){
          chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
            tabs_before+= tab.length;
          });
          waits(500);
          if (i === win_list.length-1){
            //modify version in local storage
            update_version(stored+"99");
            run_firstrun();
            //reset version to original
            update_version(stored);
            var tabs_after = 0;
            chrome.windows.getAll({populate:true},function(wind_list){
              for (var i = 0; i < wind_list.length; i++){
                chrome.tabs.query({windowId:praseInt(win_list[i].id,10),url:page},function(tab){
                  tabs_after += tab.length;
                });
                waits(500);
                if (i === wind_list.length-1){
                  expect(tabs.length).toEqual(tabs_after.length+1);
                }
              }
            });
          } else {
            expect(1).toEqual(1);
          }
        }
      });
    });
});

(function() {
  var jasmineEnv = jasmine.getEnv();
  jasmineEnv.updateInterval = 1000;

  var htmlReporter = new jasmine.HtmlReporter();

  jasmineEnv.addReporter(htmlReporter);

  jasmineEnv.specFilter = function(spec) {
    return htmlReporter.specFilter(spec);
  };

  var currentWindowOnload = window.onload;

  window.onload = function() {
    if (currentWindowOnload) {
      currentWindowOnload();
    }
    execJasmine();
  };

  function execJasmine() {
    jasmineEnv.execute();
  }

})();
<|endoftext|>


<commit_before>import RavenLogger from 'meteor/flowkey:raven';
import { Meteor } from 'meteor/meteor';

const ravenOptions = {};

const ravenLogger = new RavenLogger({
  privateDSN: Meteor.settings.sentryPrivateDSN,
  shouldCatchConsoleError: true, // default true
  trackUser: true, // default false
}, ravenOptions);

export default ravenLogger;
<commit_msg>server side config of raven fixed<commit_after>import RavenLogger from 'meteor/flowkey:raven';
import { Meteor } from 'meteor/meteor';

const ravenOptions = {};
console.log('------------ SDJKFDKJHFKSJD ')
const ravenLogger = new RavenLogger({
  privateDSN: Meteor.settings.private.sentryPrivateDSN,
  shouldCatchConsoleError: true, // default true
  trackUser: true, // default false
}, ravenOptions);

console.log(ravenLogger);

export default ravenLogger;
<|endoftext|>


<commit_before>import Bird from 'object/Bird';

class GameState extends Phaser.State {

  create() {
    this.background = this.game.add.sprite(0, 0, 'background');
    this.background.width = this.game.width;
    this.background.height = this.game.height;

    this.ground = this.game.add.sprite(0, 0, 'ground');
    this.ground.width = this.game.width * 2;
    this.ground.y = this.game.height - this.ground.height;
    this.game.physics.arcade.enable(this.ground);
    this.ground.body.velocity.x = -250;

    this.bird =  new Bird(this.game, 200, 0, 'bird');
    this.game.add.existing(this.bird);
    this.game.input.onTap.add(this.start, this);
  }

  preload() {
    this.game.stage.scale = Phaser.ScaleManager.SHOW_ALL;
    //this.game.stage.scale.setShowAll();
    window.addEventListener('resize', function () {
        this.game.scale.refresh();
    });
    this.game.scale.refresh();

    this.game.load.atlasJSONHash('bird', 'res/bird.png', 'res/bird.json');
    // background
    this.game.load.image('background', 'res/background.png');
    this.game.load.image('ground', 'res/ground.png');
  }

  update() {
    if(this.ground.x + this.ground.width / 2 <= 0) {
      this.ground.x = 0;
    }
    this.bird.update();

  }

  start() {
    this.bird.onStart();
    this.game.input.onTap.removeAll();
    this.game.input.onDown.add(this.bird.jump, this.bird);

  }

}

export default GameState;<commit_msg>load resourcesé<commit_after>import Bird from 'object/Bird';

class GameState extends Phaser.State {

  create() {
    this.background = this.game.add.sprite(0, 0, 'background');
    this.background.width = this.game.width;
    this.background.height = this.game.height;

    this.ground = this.game.add.sprite(0, 0, 'ground');
    this.ground.width = this.game.width * 2;
    this.ground.y = this.game.height - this.ground.height;
    this.game.physics.arcade.enable(this.ground);
    this.ground.body.velocity.x = -250;

    this.bird =  new Bird(this.game, 200, 0, 'bird');
    this.game.add.existing(this.bird);
    this.game.input.onTap.add(this.start, this);
  }

  preload() {
    this.game.stage.scale = Phaser.ScaleManager.SHOW_ALL;
    //this.game.stage.scale.setShowAll();
    window.addEventListener('resize', function () {
        this.game.scale.refresh();
    });
    this.game.scale.refresh();

    this.game.load.atlasJSONHash('bird', 'res/bird.png', 'res/bird.json');
    // background
    this.game.load.image('background', 'res/background.png');
    this.game.load.image('ground', 'res/ground.png');
    //pipe
    this.game.load.image('pipe', 'res/pipe.png');
    this.game.load.image('pipeEndTop', 'res/pipe-end-top.png');
    this.game.load.image('pipeEndBottom', 'res/pipe-end-bottom.png');
  }

  update() {
    if(this.ground.x + this.ground.width / 2 <= 0) {
      this.ground.x = 0;
    }
    this.bird.update();

  }

  start() {
    this.bird.onStart();
    this.game.input.onTap.removeAll();
    this.game.input.onDown.add(this.bird.jump, this.bird);

  }

}

export default GameState;<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

 foam.CLASS({
  package: 'foam.u2.view',
  name: 'ScrollTableView',
  extends: 'foam.u2.Element',

  imports: [
    'memento?',
    'stack'
  ],

  exports: [
    'as summaryView',
    'dblclick as click',
    'dblclick',
    'memento'
  ],

  requires: [
    'foam.dao.FnSink',
    'foam.mlang.sink.Count',
    'foam.u2.view.TableView',
    'foam.comics.v2.DAOControllerConfig',
    'foam.nanos.controller.Memento'
  ],

  css: `
    ^ {
      overflow: auto;
      height: 373px;
      padding-bottom: 20px;
    }
    ^table {
      position: relative;
    }
    ^table  .foam-u2-view-TableView-thead {
      z-index: 1;
      overflow: visible;
    }
  `,

  constants: [
    {
      type: 'Float',
      name: 'MIN_TOP_PAGE_PROGRESS',
      documentation: `
        If the "top" page isn't scrolled by at least this amount, make
        the top page the previous page.
        i.e. If the page that's currently in view is only scrolled 10% of the way,
        we consider the page that's above it to be the "top" page. If the page
        that's on screen is scrolled 51% of the way, then it is considered the top
        page.
      `,
      value: 0.5
    },
    {
      type: 'Integer',
      name: 'NUM_PAGES_TO_RENDER',
      value: 3
    },
    {
      type: 'Integer',
      name: 'TABLE_HEAD_HEIGHT',
      value: 51
    }
  ],

  properties: [
    {
      class: 'foam.dao.DAOProperty',
      name: 'data'
    },
    'columns',
    {
      class: 'FObjectArray',
      of: 'foam.core.Action',
      name: 'contextMenuActions'
    },
    {
      class: 'Int',
      name: 'daoCount'
    },
    'selection',
    'disableUserSelection',
    {
      class: 'Boolean',
      name: 'editColumnsEnabled',
      documentation: `
        Set to true if users should be allowed to choose which columns to use.
      `,
      value: true
    },
    {
      class: 'Int',
      name: 'rowHeight',
      documentation: 'The height of one row of the table in px.',
      value: 49
    },
    {
      name: 'table_',
      documentation: `
        A reference to the table element we use in various calculations.
      `
    },
    {
      type: 'Int',
      name: 'scrollHeight',
      expression: function(daoCount, rowHeight) {
        return rowHeight * daoCount + this.TABLE_HEAD_HEIGHT;
      }
    },
    {
      type: 'Int',
      name: 'pageSize',
      value: 30,
      documentation: 'The number of items in each "page". There are three pages.'
    },
    {
      type: 'Boolean',
      name: 'enableDynamicTableHeight',
      value: true,
    },
    {
      class: 'Boolean',
      name: 'multiSelectEnabled',
      documentation: 'Pass through to UnstyledTableView.'
    },
    {
      class: 'Map',
      name: 'selectedObjects',
      documentation: `
        The objects selected by the user when multi-select support is enabled.
        It's a map where the key is the object id and the value is the object.
        Here we simply bind it to the selectedObjects property on TableView.
      `
    },
    {
      class: 'Int',
      name: 'scrollPos_'
    },
    {
      class: 'Int',
      name: 'numPages_',
      expression: function(daoCount, pageSize) {
        return Math.ceil(daoCount / pageSize);
      }
    },
    {
      class: 'Int',
      name: 'currentTopPage_',
      expression: function(numPages_, scrollPos_, scrollHeight) {
        var scrollPercent = scrollPos_ / scrollHeight;
        var topPage = Math.floor(scrollPercent * numPages_);
        var topPageProgress = (scrollPercent * numPages_) % 1;
        if ( topPageProgress < this.MIN_TOP_PAGE_PROGRESS ) topPage = topPage - 1;
        return Math.min(Math.max(0, numPages_ - this.NUM_PAGES_TO_RENDER), Math.max(0, topPage));
      }
    },
    {
      class: 'Map',
      name: 'renderedPages_'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.comics.v2.DAOControllerConfig',
      name: 'config',
      factory: function() {
        return this.DAOControllerConfig.create({ dao: this.data });
      }
    },
    {
      name: 'dblClickListenerAction',
      factory: () => {
        return function(obj, id) {
          if ( ! this.stack ) return;

          this.stack.push({
            class: 'foam.comics.v2.DAOSummaryView',
            data: obj,
            config: this.config,
            idOfRecord: id
          }, this);
        }
      }
    },
    'currentMemento',
    {
      class: 'Boolean',
      name: 'isInit'
    },
    'tableWrapper_'
  ],

  reactions: [
    ['', 'propertyChange.currentTopPage_', 'updateRenderedPages_'],
    ['', 'propertyChange.table_',          'updateRenderedPages_']
  ],

  methods: [
    function init() {
      this.onDetach(this.data$proxy.listen(this.FnSink.create({ fn: this.updateCount })));
      this.updateCount();

      if ( this.memento )
        this.currentMemento$ = this.memento.tail$;
    },

    function initE() {
      if ( this.currentMemento ) {
        var mementoHead = this.currentMemento.head;

        var of = this.data.of || this.config.of;
        if ( mementoHead === 'Create' && of ) {
          this.stack.push({
            class: 'foam.comics.v2.DAOCreateView',
            data: ((this.config.factory && this.config.factory$cls) ||  this.data.of).create({ mode: 'create'}, this),
            config$: this.config$,
            of: of
          }, this.__subContext__);
          return;
        }

        var id = mementoHead;
        if ( of ) {
          if ( ! foam.core.MultiPartID.isInstance(of.ID) ) {
            id = of.ID.fromString(mementoHead);
          } else {
            id = of.ID.of.create();
            mementoHead = '{' + mementoHead.replaceAll('=', ':') + '}';
            var idFromJSON = foam.json.parseString(mementoHead);
            for ( var key in idFromJSON ) {
              var axiom = of.ID.of.getAxiomByName(key);
              if ( axiom )
                axiom.set(id, idFromJSON[key]);
            }
          }
        }

        this.stack.push({
          class: 'foam.comics.v2.DAOSummaryView',
          data: null,
          config: this.config,
          idOfRecord: id
        }, this);
        return;
      }

      this.
        start('div', {}, this.tableWrapper_$).
          addClass(this.myClass()).
          on('scroll', this.onScroll).
          start(this.TableView, {
            data: foam.dao.NullDAO.create({of: this.data.of}),
            columns: this.columns,
            contextMenuActions: this.contextMenuActions,
            selection$: this.selection$,
            editColumnsEnabled: this.editColumnsEnabled,
            disableUserSelection: this.disableUserSelection,
            multiSelectEnabled: this.multiSelectEnabled,
            selectedObjects$: this.selectedObjects$
          }, this.table_$).
            addClass(this.myClass('table')).
            style({
              height: this.scrollHeight$.map(h => h + 'px')
            }).
          end().
        end();

      /*
        to be used in cases where we don't want the whole table to
        take the whole page (i.e. we need multiple tables)
        and enableDynamicTableHeight can be switched off
      */
      if ( this.enableDynamicTableHeight ) {
        this.onDetach(this.onload.sub(this.updateTableHeight));
        window.addEventListener('resize', this.updateTableHeight);
        this.onDetach(() => {
          window.removeEventListener('resize', this.updateTableHeight);
        });
      }
    }
  ],

  listeners: [
    {
      name: 'refresh',
      isFramed: true,
      code: function() {
        Object.keys(this.renderedPages_).forEach(i => {
          this.renderedPages_[i].remove();
          delete this.renderedPages_[i];
        });
        this.updateRenderedPages_();
        if ( this.el() && ! this.isInit && this.memento && this.memento.paramsObj.r ) {
          var scroll = this.memento.paramsObj.r * this.rowHeight;
          scroll = scroll >= this.rowHeight && scroll < this.scrollHeight ? scroll : 0;

          if ( this.childNodes && this.childNodes.length > 0 )
            document.getElementById(this.tableWrapper_.id).scrollTop = scroll;

          this.isInit = true;
        } else if ( this.el() ) this.el().scrollTop = 0;
      }
    },
    {
      name: 'updateCount',
      isFramed: true,
      code: function() {
        return this.data$proxy.select(this.Count.create()).then((s) => {
          this.daoCount = s.value;
          this.refresh();
        });
      }
    },
    {
      name: 'updateRenderedPages_',
      isFramed: true,
      code: function() {
        if ( ! this.table_ ) return;

        // Remove any pages that are no longer on screen to save on
        // the amount of DOM we add to the page.
        Object.keys(this.renderedPages_).forEach(i => {
          if ( i >= this.currentTopPage_ && i < this.currentTopPage_ + this.NUM_PAGES_TO_RENDER ) return;
          this.renderedPages_[i].remove();
          delete this.renderedPages_[i];
        });

        // Add any pages that are not already rendered.
        for ( var i = 0; i < Math.min(this.numPages_, this.NUM_PAGES_TO_RENDER) ; i++) {
          var page = this.currentTopPage_ + i;
          if ( this.renderedPages_[page] ) continue;
          var dao = this.data$proxy.limit(this.pageSize).skip(page * this.pageSize);
          var tbody = this.table_.slotE_(this.table_.rowsFrom(dao));
          tbody.style({
            position: 'absolute',
            width: '100%',
            top: this.TABLE_HEAD_HEIGHT + page * this.pageSize * this.rowHeight + 'px'
          });
          this.table_.add(tbody);
          this.renderedPages_[page] = tbody;
        }
      }
    },
    {
      name: 'onScroll',
      isFramed: true,
      code: function(e) {
        this.scrollPos_ = e.target.scrollTop;
        if ( this.memento ) {
          this.memento.paramsObj.r = this.scrollPos_ >= this.rowHeight && this.scrollPos_ < this.scrollHeight ? Math.floor( this.scrollPos_  / this.rowHeight) : 0;
          this.memento.paramsObj = foam.Object.clone(this.memento.paramsObj);
        }
      }
    },
    {
      name: 'updateTableHeight',
      code: function() {
        // Find the distance from the top of the table to the top of the screen.
        var distanceFromTop = this.el().getBoundingClientRect().y;

        // Calculate the remaining space we have to make use of.
        var remainingSpace = window.innerHeight - distanceFromTop;

        // TODO: Do we want to do this?
        // Leave space for the footer.
        remainingSpace -= 44;

        this.style({ height: `${remainingSpace}px` });
      }
    },
    function dblclick(obj, id) {
      this.dblClickListenerAction(obj, id);
    }
  ]
});
<commit_msg>Np 3651/fixing scroll (#4869)<commit_after>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

 foam.CLASS({
  package: 'foam.u2.view',
  name: 'ScrollTableView',
  extends: 'foam.u2.Element',

  imports: [
    'memento?',
    'stack'
  ],

  exports: [
    'as summaryView',
    'dblclick as click',
    'dblclick',
    'memento'
  ],

  requires: [
    'foam.dao.FnSink',
    'foam.mlang.sink.Count',
    'foam.u2.view.TableView',
    'foam.comics.v2.DAOControllerConfig',
    'foam.nanos.controller.Memento'
  ],

  css: `
    ^ {
      overflow: auto;
      height: calc(100% - 65px);
      padding-bottom: 20px;
    }
    ^table {
      position: relative;
    }
    ^table  .foam-u2-view-TableView-thead {
      z-index: 1;
      overflow: visible;
    }
  `,

  constants: [
    {
      type: 'Float',
      name: 'MIN_TOP_PAGE_PROGRESS',
      documentation: `
        If the "top" page isn't scrolled by at least this amount, make
        the top page the previous page.
        i.e. If the page that's currently in view is only scrolled 10% of the way,
        we consider the page that's above it to be the "top" page. If the page
        that's on screen is scrolled 51% of the way, then it is considered the top
        page.
      `,
      value: 0.5
    },
    {
      type: 'Integer',
      name: 'NUM_PAGES_TO_RENDER',
      value: 3
    },
    {
      type: 'Integer',
      name: 'TABLE_HEAD_HEIGHT',
      value: 51
    }
  ],

  properties: [
    {
      class: 'foam.dao.DAOProperty',
      name: 'data'
    },
    'columns',
    {
      class: 'FObjectArray',
      of: 'foam.core.Action',
      name: 'contextMenuActions'
    },
    {
      class: 'Int',
      name: 'daoCount'
    },
    'selection',
    'disableUserSelection',
    {
      class: 'Boolean',
      name: 'editColumnsEnabled',
      documentation: `
        Set to true if users should be allowed to choose which columns to use.
      `,
      value: true
    },
    {
      class: 'Int',
      name: 'rowHeight',
      documentation: 'The height of one row of the table in px.',
      value: 49
    },
    {
      name: 'table_',
      documentation: `
        A reference to the table element we use in various calculations.
      `
    },
    {
      type: 'Int',
      name: 'scrollHeight',
      expression: function(daoCount, rowHeight) {
        return rowHeight * daoCount + this.TABLE_HEAD_HEIGHT;
      }
    },
    {
      type: 'Int',
      name: 'pageSize',
      value: 30,
      documentation: 'The number of items in each "page". There are three pages.'
    },
    {
      type: 'Boolean',
      name: 'enableDynamicTableHeight',
      value: true,
    },
    {
      class: 'Boolean',
      name: 'multiSelectEnabled',
      documentation: 'Pass through to UnstyledTableView.'
    },
    {
      class: 'Map',
      name: 'selectedObjects',
      documentation: `
        The objects selected by the user when multi-select support is enabled.
        It's a map where the key is the object id and the value is the object.
        Here we simply bind it to the selectedObjects property on TableView.
      `
    },
    {
      class: 'Int',
      name: 'scrollPos_'
    },
    {
      class: 'Int',
      name: 'numPages_',
      expression: function(daoCount, pageSize) {
        return Math.ceil(daoCount / pageSize);
      }
    },
    {
      class: 'Int',
      name: 'currentTopPage_',
      expression: function(numPages_, scrollPos_, scrollHeight) {
        var scrollPercent = scrollPos_ / scrollHeight;
        var topPage = Math.floor(scrollPercent * numPages_);
        var topPageProgress = (scrollPercent * numPages_) % 1;
        if ( topPageProgress < this.MIN_TOP_PAGE_PROGRESS ) topPage = topPage - 1;
        return Math.min(Math.max(0, numPages_ - this.NUM_PAGES_TO_RENDER), Math.max(0, topPage));
      }
    },
    {
      class: 'Map',
      name: 'renderedPages_'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.comics.v2.DAOControllerConfig',
      name: 'config',
      factory: function() {
        return this.DAOControllerConfig.create({ dao: this.data });
      }
    },
    {
      name: 'dblClickListenerAction',
      factory: () => {
        return function(obj, id) {
          if ( ! this.stack ) return;

          this.stack.push({
            class: 'foam.comics.v2.DAOSummaryView',
            data: obj,
            config: this.config,
            idOfRecord: id
          }, this);
        }
      }
    },
    'currentMemento',
    {
      class: 'Boolean',
      name: 'isInit'
    },
    'tableWrapper_'
  ],

  reactions: [
    ['', 'propertyChange.currentTopPage_', 'updateRenderedPages_'],
    ['', 'propertyChange.table_',          'updateRenderedPages_']
  ],

  methods: [
    function init() {
      this.onDetach(this.data$proxy.listen(this.FnSink.create({ fn: this.updateCount })));
      this.updateCount();

      if ( this.memento )
        this.currentMemento$ = this.memento.tail$;
    },

    function initE() {
      if ( this.currentMemento ) {
        var mementoHead = this.currentMemento.head;

        var of = this.data.of || this.config.of;
        if ( mementoHead === 'Create' && of ) {
          this.stack.push({
            class: 'foam.comics.v2.DAOCreateView',
            data: ((this.config.factory && this.config.factory$cls) ||  this.data.of).create({ mode: 'create'}, this),
            config$: this.config$,
            of: of
          }, this.__subContext__);
          return;
        }

        var id = mementoHead;
        if ( of ) {
          if ( ! foam.core.MultiPartID.isInstance(of.ID) ) {
            id = of.ID.fromString(mementoHead);
          } else {
            id = of.ID.of.create();
            mementoHead = '{' + mementoHead.replaceAll('=', ':') + '}';
            var idFromJSON = foam.json.parseString(mementoHead);
            for ( var key in idFromJSON ) {
              var axiom = of.ID.of.getAxiomByName(key);
              if ( axiom )
                axiom.set(id, idFromJSON[key]);
            }
          }
        }

        this.stack.push({
          class: 'foam.comics.v2.DAOSummaryView',
          data: null,
          config: this.config,
          idOfRecord: id
        }, this);
        return;
      }

      this.
        start('div', {}, this.tableWrapper_$).
          addClass(this.myClass()).
          on('scroll', this.onScroll).
          start(this.TableView, {
            data: foam.dao.NullDAO.create({of: this.data.of}),
            columns: this.columns,
            contextMenuActions: this.contextMenuActions,
            selection$: this.selection$,
            editColumnsEnabled: this.editColumnsEnabled,
            disableUserSelection: this.disableUserSelection,
            multiSelectEnabled: this.multiSelectEnabled,
            selectedObjects$: this.selectedObjects$
          }, this.table_$).
            addClass(this.myClass('table')).
            style({
              height: this.scrollHeight$.map(h => h + 'px')
            }).
          end().
        end();

      /*
        to be used in cases where we don't want the whole table to
        take the whole page (i.e. we need multiple tables)
        and enableDynamicTableHeight can be switched off
      */
      if ( this.enableDynamicTableHeight ) {
        this.onDetach(this.onload.sub(this.updateTableHeight));
        window.addEventListener('resize', this.updateTableHeight);
        this.onDetach(() => {
          window.removeEventListener('resize', this.updateTableHeight);
        });
      }
    }
  ],

  listeners: [
    {
      name: 'refresh',
      isFramed: true,
      code: function() {
        Object.keys(this.renderedPages_).forEach(i => {
          this.renderedPages_[i].remove();
          delete this.renderedPages_[i];
        });
        this.updateRenderedPages_();
        if ( this.el() && ! this.isInit && this.memento && this.memento.paramsObj.r ) {
          var scroll = this.memento.paramsObj.r * this.rowHeight;
          scroll = scroll >= this.rowHeight && scroll < this.scrollHeight ? scroll : 0;

          if ( this.childNodes && this.childNodes.length > 0 )
            document.getElementById(this.tableWrapper_.id).scrollTop = scroll;

          this.isInit = true;
        } else if ( this.el() ) this.el().scrollTop = 0;
      }
    },
    {
      name: 'updateCount',
      isFramed: true,
      code: function() {
        return this.data$proxy.select(this.Count.create()).then((s) => {
          this.daoCount = s.value;
          this.refresh();
        });
      }
    },
    {
      name: 'updateRenderedPages_',
      isFramed: true,
      code: function() {
        if ( ! this.table_ ) return;

        // Remove any pages that are no longer on screen to save on
        // the amount of DOM we add to the page.
        Object.keys(this.renderedPages_).forEach(i => {
          if ( i >= this.currentTopPage_ && i < this.currentTopPage_ + this.NUM_PAGES_TO_RENDER ) return;
          this.renderedPages_[i].remove();
          delete this.renderedPages_[i];
        });

        // Add any pages that are not already rendered.
        for ( var i = 0; i < Math.min(this.numPages_, this.NUM_PAGES_TO_RENDER) ; i++) {
          var page = this.currentTopPage_ + i;
          if ( this.renderedPages_[page] ) continue;
          var dao = this.data$proxy.limit(this.pageSize).skip(page * this.pageSize);
          var tbody = this.table_.slotE_(this.table_.rowsFrom(dao));
          tbody.style({
            position: 'absolute',
            width: '100%',
            top: this.TABLE_HEAD_HEIGHT + page * this.pageSize * this.rowHeight + 'px'
          });
          this.table_.add(tbody);
          this.renderedPages_[page] = tbody;
        }
      }
    },
    {
      name: 'onScroll',
      isFramed: true,
      code: function(e) {
        this.scrollPos_ = e.target.scrollTop;
        if ( this.memento ) {
          this.memento.paramsObj.r = this.scrollPos_ >= this.rowHeight && this.scrollPos_ < this.scrollHeight ? Math.floor( this.scrollPos_  / this.rowHeight) : 0;
          this.memento.paramsObj = foam.Object.clone(this.memento.paramsObj);
        }
      }
    },
    {
      name: 'updateTableHeight',
      code: function() {
        // Find the distance from the top of the table to the top of the screen.
        var distanceFromTop = this.el().getBoundingClientRect().y;

        // Calculate the remaining space we have to make use of.
        var remainingSpace = window.innerHeight - distanceFromTop;

        // TODO: Do we want to do this?
        // Leave space for the footer.
        remainingSpace -= 44;

        this.style({ height: `${remainingSpace}px` });
      }
    },
    function dblclick(obj, id) {
      this.dblClickListenerAction(obj, id);
    }
  ]
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.CLASS({
  package: 'foam.u2.view',
  name: 'StringArrayView',
  extends: 'foam.u2.tag.Input',
  properties: [
    {
      name: 'data',
      preSet: function(o, d) {
        return d;
      }
    },
    {
      class: 'Function',
      name: 'valueToText',
      value: function(value) {
        return value.map(function(m) {
          return m.replace("\\", "\\\\").replace(",", "\\,");
        }).join(',');
      }
    },
    {
      class: 'Function',
      name: 'textToValue',
      value: function(text) {
        if ( ! text ) return [];

        var value = [];
        var escape = false;
        var start = 0;
        for ( var i = 0 ; i < text.length ; i++ ) {
          if ( escape ) {
            escape = false;
            continue;
          }

          if ( i == text.length - 1 ) {
            value.push(text.substring(start, i+1).replace(/\\(.)/, "$0"));
          } else if ( text[i] == ',' || i == text.length - 1 ) {
            value.push(text.substring(start, i).replace(/\\(.)/, "$0"));
            start = ++i;
          } else if ( text[i] == '\\' ) {
            escape = true;
          }
        }

        return value;
      }
    }
  ],
  methods: [
    function link() {
      this.attrSlot().relateFrom(this.data$, this.textToValue, this.valueToText);
    }
  ]
});
<commit_msg>Formatting.<commit_after>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.u2.view',
  name: 'StringArrayView',
  extends: 'foam.u2.tag.Input',

  properties: [
    {
      name: 'data',
      preSet: function(o, d) { return d; }
    },
    {
      class: 'Function',
      name: 'valueToText',
      value: function(value) {
        return value.map(function(m) {
          return m.replace("\\", "\\\\").replace(",", "\\,");
        }).join(',');
      }
    },
    {
      class: 'Function',
      name: 'textToValue',
      value: function(text) {
        if ( ! text ) return [];

        var value  = [];
        var escape = false;
        var start  = 0;
        for ( var i = 0 ; i < text.length ; i++ ) {
          if ( escape ) {
            escape = false;
            continue;
          }

          if ( i == text.length - 1 ) {
            value.push(text.substring(start, i+1).replace(/\\(.)/, "$0"));
          } else if ( text[i] == ',' || i == text.length - 1 ) {
            value.push(text.substring(start, i).replace(/\\(.)/, "$0"));
            start = ++i;
          } else if ( text[i] == '\\' ) {
            escape = true;
          }
        }

        return value;
      }
    }
  ],

  methods: [
    function link() {
      this.attrSlot().relateFrom(this.data$, this.textToValue, this.valueToText);
    }
  ]
});
<|endoftext|>


<commit_before>/*global canCall */

/*
Description:
Relies on `Array.forEach` or `Function.prototype.call` providing greatest browser support
*/

var forEach;

if (Array.prototype.forEach) {
	forEach = function(elements, callback, thisObject) {
		elements.forEach(callback, thisObject);
	};
}else if (canCall) {
	forEach = function(elements, callback, thisObject) {
		for (var i = 0, l = elements.length; i < l; i++) {
			callback.call(thisObject, elements[i], i, elements);
		}
	};
}<commit_msg>Fix whitespace<commit_after>/*global canCall */

/*
Description:
Relies on `Array.forEach` or `Function.prototype.call` providing greatest browser support
*/

var forEach;

if (Array.prototype.forEach) {
        forEach = function(elements, callback, thisObject) {
                elements.forEach(callback, thisObject);
        };
} else if (canCall) {
        forEach = function(elements, callback, thisObject) {
                for (var i = 0, l = elements.length; i < l; i++) {
                        callback.call(thisObject, elements[i], i, elements);
                }
        };
}
<|endoftext|>


<commit_before>function SpriteRendererSystem(layer) {
  IteratingSystem.call(this, [Position.name, Display.name]);
  this.l = layer;
}

__extend(SpriteRendererSystem, IteratingSystem, {
  add: function(entity) {
    this.l.add(Pixelwars.c(entity, Display.name).gfx);
  },
  remove: function(entity) {
    this.l.remove(Pixelwars.c(entity, Display.name).gfx);
  },
  update: function(elapsed) {
    IteratingSystem.prototype.update.call(this, elapsed);

    // Sort elements
    this.c.sort(function(objA, objB) {
      return objA.y > objB.y ? 1 : -1;
    });

    // Render the frame
    Buffer.render();
  },
  onUpdate: function(entity, elapsed) {
    var position = Pixelwars.c(entity, Position.name);
    var gfx = Pixelwars.c(entity, Display.name).gfx;

    // Update asset position
    gfx.x = position.x | 0;
    gfx.y = position.y | 0;

    // Update animation
    if (gfx instanceof AnimatedSprite) {
      gfx.advance(elapsed * 1000 | 0);
    }
  }
});
<commit_msg>Fix y sorting<commit_after>function SpriteRendererSystem(layer) {
  IteratingSystem.call(this, [Position.name, Display.name]);
  this.l = layer;
}

__extend(SpriteRendererSystem, IteratingSystem, {
  add: function(entity) {
    this.l.add(Pixelwars.c(entity, Display.name).gfx);
  },
  remove: function(entity) {
    this.l.remove(Pixelwars.c(entity, Display.name).gfx);
  },
  update: function(elapsed) {
    IteratingSystem.prototype.update.call(this, elapsed);

    // Sort elements
    this.l._c.sort(function(objA, objB) {
      return objA.y - objB.y;
    });

    // Render the frame
    Buffer.render();
  },
  onUpdate: function(entity, elapsed) {
    var position = Pixelwars.c(entity, Position.name);
    var gfx = Pixelwars.c(entity, Display.name).gfx;

    // Update asset position
    gfx.x = position.x | 0;
    gfx.y = position.y | 0;

    // Update animation
    if (gfx instanceof AnimatedSprite) {
      gfx.advance(elapsed * 1000 | 0);
    }
  }
});
<|endoftext|>


<commit_before>var request = require('superagent-promise')(require('superagent'), Promise);
var Papa = require('babyparse');
var CCE = require('.');

function getContaminantsReferenceList() {

    return Promise.all([
        request.get('https://googledocs.cheminfo.org/spreadsheets/d/1LrJCl9-xSZKhGA9Y8nKVkYwB-mEOHBkTXg5qYXeFpZY/export?format=tsv').end(),
        request.get('https://googledocs.cheminfo.org/spreadsheets/d/1C_H9aiJyu9M9in7sHMOaz-d3Sv758rE72oLxEKH9ioA/export?format=tsv').end()
    ]).then(function (results) {
        return parse(results[0].text, results[1].text);
    });

    function parse(tsv, tsvReferences) {
        var contaminants=Papa.parse(tsv,
            {
                delimiter:"\t",
                header: true
            }
        ).data;

        var referencesArray=Papa.parse(tsvReferences,
            {
                delimiter:"\t",
                header: true
            }
        ).data;

        var references={};
        referencesArray.forEach(
            function(ref) {
                references[ref.label]=ref;
            }
        );

// contaminants=contaminants.slice(20,25);

        var results=[];

        for (var contaminant of contaminants) {
            // we add references
            var refs=contaminant.references.split(/[ ,]+/);
            contaminant.references=[];
            for (var ref of refs) {
                contaminant.references.push(
                    references[ref]
                );
            }

            // we need to calculate all the possibilities
            var mfs=CCE.combineMFs([contaminant.mf, contaminant.modif]);
            for (var mf of mfs) {
                mf.info=contaminant;
                mf.ESI = contaminant.ESI==='X' ? true : false;
                mf.MALDI = contaminant.MALDI==='X' ? true : false;
                mf.positive = contaminant.positive==='X' ? true : false;
                mf.negative = contaminant.negative==='X' ? true : false;
                mf.similarity='';
                mf.mf=CCE.analyseMF(mf.mf).mf;
                results.push(mf)
            }
        }
        return results;
    }

}

module.exports = getContaminantsReferenceList;

<commit_msg>Update getContaminantsReferenceList.js<commit_after>var request = require('superagent-promise')(require('superagent'), Promise);
var Papa = require('papaparse');
var CCE = require('.');

function getContaminantsReferenceList() {

    return Promise.all([
        request.get('https://googledocs.cheminfo.org/spreadsheets/d/1LrJCl9-xSZKhGA9Y8nKVkYwB-mEOHBkTXg5qYXeFpZY/export?format=tsv').end(),
        request.get('https://googledocs.cheminfo.org/spreadsheets/d/1C_H9aiJyu9M9in7sHMOaz-d3Sv758rE72oLxEKH9ioA/export?format=tsv').end()
    ]).then(function (results) {
        return parse(results[0].text, results[1].text);
    });

    function parse(tsv, tsvReferences) {
        var contaminants=Papa.parse(tsv,
            {
                delimiter:"\t",
                header: true
            }
        ).data;

        var referencesArray=Papa.parse(tsvReferences,
            {
                delimiter:"\t",
                header: true
            }
        ).data;

        var references={};
        referencesArray.forEach(
            function(ref) {
                references[ref.label]=ref;
            }
        );

// contaminants=contaminants.slice(20,25);

        var results=[];

        for (var contaminant of contaminants) {
            // we add references
            var refs=contaminant.references.split(/[ ,]+/);
            contaminant.references=[];
            for (var ref of refs) {
                contaminant.references.push(
                    references[ref]
                );
            }

            // we need to calculate all the possibilities
            var mfs=CCE.combineMFs([contaminant.mf, contaminant.modif]);
            for (var mf of mfs) {
                mf.info=contaminant;
                mf.ESI = contaminant.ESI==='X' ? true : false;
                mf.MALDI = contaminant.MALDI==='X' ? true : false;
                mf.positive = contaminant.positive==='X' ? true : false;
                mf.negative = contaminant.negative==='X' ? true : false;
                mf.similarity='';
                mf.mf=CCE.analyseMF(mf.mf).mf;
                results.push(mf)
            }
        }
        return results;
    }

}

module.exports = getContaminantsReferenceList;

<|endoftext|>


<commit_before>/*
 TaskOnFly allows you easy manage your tasks and task lists on the fly from your mobile or desktop device.
 Copyright (C) 2014-2015  Valerii Zinchenko

 This file is part of TaskOnFly.

 TaskOnFly is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 TaskOnFly is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with TaskOnFly.  If not, see <http://www.gnu.org/licenses/>.

 All source files are available at: http://github.com/valerii-zinchenko/TaskOnFly
 */

/**
 * @file It contains the implementation of an [abstract MVC module]{@link MVCModule}
 *
 * @author Valerii Zinchenko
 *
 * @version 4.0.0
 */

'use strict';

/**
 * Abstract MVC module.
 * It combines and control model and its states.
 *
 * @type {Class}
 *
 * @throws {Error} Incorrect types of input arguments. Expected: Object model, Object states
 *
 * @constructor
 * @param {Object} model - Model.
 * @param {Object} states - Object of model's states, where the key is a state name and value is a state object.
 */
var MVCModule = new Class({
	/**
	 * Module's model
	 *
	 * @type {Object}
	 */
	model: null,

	/**
	 * Collection of model's states
	 *
	 * @type {Object}
	 */
	states: null,

	// constructor
	initialize: function(model, states) {
		if (!utils.is(model, 'Object') || !utils.is(states, 'Object')) {
			throw new Error('Incorrect types of input arguments. Expected: Object model, Object states');
		}

		this.model = model;
		this.states = states;
	},

	/**
	 * Specify which state will be used.
	 * this.view and this.control will point to the View and Control of specific model state.
	 *
	 * @throws {Error} Incorrect type of the input argument. Expected: String stateName
	 * @throws {Error} Undefined state "{stateName}"
	 *
	 * @param {string} [stateName] - State name. Used only when states were explicit defined
	 * @return {State}
	 */
	useState: function(stateName) {
		if (this.states._implicit) {
			return this.states._implicit;
		}

		if (!utils.is(stateName, 'String')) {
			throw new Error('Incorrect type of the input argument. Expected: String stateName');
		}

		var state = this.states[stateName];
		if (!state) {
			throw new Error('Undefined state "' + stateName + '"');
		}

		return state;
	}
});
<commit_msg>remove implicit states<commit_after>/*
 TaskOnFly allows you easy manage your tasks and task lists on the fly from your mobile or desktop device.
 Copyright (C) 2014-2015  Valerii Zinchenko

 This file is part of TaskOnFly.

 TaskOnFly is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 TaskOnFly is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with TaskOnFly.  If not, see <http://www.gnu.org/licenses/>.

 All source files are available at: http://github.com/valerii-zinchenko/TaskOnFly
 */

/**
 * @file It contains the implementation of an [abstract MVC module]{@link MVCModule}
 *
 * @author Valerii Zinchenko
 *
 * @version 4.0.0
 */

'use strict';

/**
 * Abstract MVC module.
 * It combines and control model and its states.
 *
 * @type {Class}
 *
 * @throws {Error} Incorrect types of input arguments. Expected: Object model, Object states
 *
 * @constructor
 * @param {Object} model - Model.
 * @param {Object} states - Object of model's states, where the key is a state name and value is a state object.
 */
var MVCModule = new Class({
	/**
	 * Module's model
	 *
	 * @type {Object}
	 */
	model: null,

	/**
	 * Collection of model's states
	 *
	 * @type {Object}
	 */
	states: null,

	// constructor
	initialize: function(model, states) {
		if (!utils.is(model, 'Object') || !utils.is(states, 'Object')) {
			throw new Error('Incorrect types of input arguments. Expected: Object model, Object states');
		}

		this.model = model;
		this.states = states;
	},

	/**
	 * Specify which state will be used.
	 * this.view and this.control will point to the View and Control of specific model state.
	 *
	 * @throws {Error} Incorrect type of the input argument. Expected: String stateName
	 * @throws {Error} Undefined state "{stateName}"
	 *
	 * @param {String} stateName - State name
	 * @return {State}
	 */
	useState: function(stateName) {
		if (!utils.is(stateName, 'String')) {
			throw new Error('Incorrect type of the input argument. Expected: String stateName');
		}

		var state = this.states[stateName];
		if (!state) {
			throw new Error('Undefined state "' + stateName + '"');
		}

		return state;
	}
});
<|endoftext|>


<commit_before>// mocha.js tests for the functions dealing with Curious queries
(function () {
'use strict';

var expect = require('chai').expect;
var curious = require('../curious2.js');

describe('CuriousQuery', function () {
  describe('#query', function () {
    var expectedQuery = (
      'Experiment(id=302), Experiment.reaction_set, '
       + 'Reaction.dataset_set, Dataset.attachment_set'
    );

    // Fake constructor
    function Dataset() {}

    it('should return the empty string with no terms', function () {
      expect((new curious.CuriousQuery()).query()).to.equal('');
    });

    it('should return the correct query string', function () {
      var q = (new curious.CuriousQuery())
        .start('Experiment(id=302)', 'experiments')
        .follow('Experiment.reaction_set', 'reactions')
        .follow('Reaction.dataset_set', 'datasets').wrapWith(Dataset)
        .follow('Dataset.attachment_set', 'attachments');

      expect(q.query()).to.equal(expectedQuery);
    });

    it('should allow shortcuts', function () {
      // Terser version of the same query
      var q = new curious.CuriousQuery('Experiment(id=302)', 'experiment')
        .follow('Experiment.reaction_set', 'reactions')
        .follow('Reaction.dataset_set', 'dataset', Dataset)
        .follow('Dataset.attachment_set', 'attachments');

      expect(q.query()).to.equal(expectedQuery);
    });
  });

  describe('#start', function () {
    var startingTerm = 'Experiment(id=302)';

    // Fake constructor
    function Experiment() { return this; }
    function experimentFactory() { return Object.create(new Experiment()); }

    it('should start the query', function () {
      var q = (new curious.CuriousQuery()).start(startingTerm, 'experiments');

      expect(q.query()).to.equal(startingTerm);
    });

    it('should require both a term and a relationship', function () {
      expect(function () {
        (new curious.CuriousQuery()).start();
      }).to.throw(/term/);

      expect(function () {
        (new curious.CuriousQuery()).start(startingTerm);
      }).to.throw(/relationship/);
    });

    it('should allow custom constructors', function () {
      var q = (new curious.CuriousQuery())
        .start(startingTerm, 'experiments')
        .wrapWith(Experiment);

      expect(q.query()).to.equal(startingTerm);

      expect(q.objectFactories).to.have.length(1);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
    });

    it('should allow function factories', function () {
      var q = (new curious.CuriousQuery())
        .start(startingTerm, 'experiments')
        .wrapDynamically(experimentFactory);

      expect(q.query()).to.equal(startingTerm);

      expect(q.objectFactories).to.have.length(1);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
    });

    it('should allow shortcuts', function () {
      var q = new curious.CuriousQuery(startingTerm, 'experiments', Experiment);
      var q2 = new curious.CuriousQuery(startingTerm, 'experiments', experimentFactory);

      expect(q.query()).to.equal(startingTerm);

      expect(q.objectFactories).to.have.length(1);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);

      expect(q2.objectFactories).to.have.length(1);
      expect(q2.objectFactories[0]()).to.be.an.instanceof(Experiment);
    });
  });

  describe('#follow', function () {
    var expectedQuery = 'Experiment(id=302), Experiment.reaction_set';
    var startingQuery;

    // Fake constructor
    function Experiment() { return this; }
    function Reaction() { return this; }
    function reactionFactory() { return Object.create(new Reaction()); }

    beforeEach(function () {
      startingQuery = new curious.CuriousQuery(
        'Experiment(id=302)', 'experiments', Experiment
      );
    });

    it('should append to the query with a comma', function () {
      var q = startingQuery
        .follow('Experiment.reaction_set', 'reactions');
      expect(q.query()).to.equal(expectedQuery);
    });

    it('should successfully allow terms without commas', function () {
      var q = startingQuery
        .follow('Experiment.reaction_set Reaction.dataset_set', 'datasets');

      expect(q.query()).to.equal(expectedQuery + ' Reaction.dataset_set');
    });

    it('should require both a term and a relationship', function () {
      expect(function () {
        startingQuery.follow();
      }).to.throw(/term/);

      expect(function () {
        startingQuery.follow('Experiment.reaction_set');
      }).to.throw(/relationship/);
    });

    it('should allow custom constructors', function () {
      var q = startingQuery
        .follow('Experiment.reaction_set', 'reactions')
        .wrapWith(Reaction);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(2);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Reaction);
    });

    it('should allow function factories', function () {
      var q = startingQuery
        .follow('Experiment.reaction_set', 'reactions')
        .wrapDynamically(reactionFactory);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(2);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Reaction);
    });

    it('should allow shortcuts', function () {
      var q = startingQuery.clone()
        .follow('Experiment.reaction_set', 'reactions', Reaction);
      var q2 = startingQuery.clone()
        .follow('Experiment.reaction_set', 'reactions', reactionFactory);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(2);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Reaction);

      expect(q2.query()).to.equal(expectedQuery);

      expect(q2.objectFactories).to.have.length(2);
      expect(q2.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q2.objectFactories[1]()).to.be.an.instanceof(Reaction);
    });

  });

  describe('#with', function () {
    var expectedQuery = (
      'Experiment(id=302)'
      + ' ?(Experiment.compounds_of_interest)'
      + ' Experiment.reaction_set'
    );
    var startingQuery;

    // Fake constructor
    function Experiment() { return this; }
    function Reaction() { return this; }
    function Compound() { return this; }
    function compoundFactory() { return Object.create(new Compound()); }

    beforeEach(function () {
      startingQuery = new curious.CuriousQuery(
        'Experiment(id=302)', 'experiments', Experiment
      );
    });

    it('should append to the query with a groupng', function () {
      var q = startingQuery
        .with('Experiment.compounds_of_interest', 'compounds')
        .follow('Experiment.reaction_set', 'reactions');

      expect(q.query()).to.equal(expectedQuery);
    });

    it('should successfully allow terms without commas inside the group', function () {
      var q = startingQuery
        .with('Experiment.compounds_of_interest Compound.standard_set', 'standards')
        .follow('Experiment.reaction_set', 'reactions');

      expect(q.query()).to.equal(
        'Experiment(id=302)'
        + ' ?(Experiment.compounds_of_interest Compound.standard_set)'
        + ' Experiment.reaction_set'
      );
    });

    it('should require both a term and a relationship', function () {
      expect(function () {
        startingQuery.with();
      }).to.throw(/term/);

      expect(function () {
        startingQuery.with('Experiment.reaction_set');
      }).to.throw(/relationship/);
    });

    it('should allow custom constructors', function () {
      var q = startingQuery
        .with('Experiment.compounds_of_interest', 'compounds').wrapWith(Compound)
        .follow('Experiment.reaction_set', 'reactions').wrapWith(Reaction);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(3);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Compound);
      expect(q.objectFactories[2]()).to.be.an.instanceof(Reaction);
    });

    it('should allow function factories', function () {
      var q = startingQuery
        .with('Experiment.compounds_of_interest', 'compounds')
          .wrapDynamically(compoundFactory)
        .follow('Experiment.reaction_set', 'reactions').wrapWith(Reaction);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(3);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Compound);
      expect(q.objectFactories[2]()).to.be.an.instanceof(Reaction);
    });

    it('should allow shortcuts', function () {
      var q = startingQuery.clone()
        .with('Experiment.compounds_of_interest', 'compounds', Compound)
        .follow('Experiment.reaction_set', 'reactions').wrapWith(Reaction);
      var q2 = startingQuery.clone()
        .with('Experiment.compounds_of_interest', 'compounds', compoundFactory)
        .follow('Experiment.reaction_set', 'reactions').wrapWith(Reaction);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(3);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Compound);
      expect(q.objectFactories[2]()).to.be.an.instanceof(Reaction);

      expect(q2.query()).to.equal(expectedQuery);

      expect(q2.objectFactories).to.have.length(3);
      expect(q2.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q2.objectFactories[1]()).to.be.an.instanceof(Compound);
      expect(q2.objectFactories[2]()).to.be.an.instanceof(Reaction);
    });
  });
});

}());
<commit_msg>Add tests for CuriousQuery#having and #notHaving<commit_after>// mocha.js tests for the functions dealing with Curious queries
(function () {
'use strict';

var expect = require('chai').expect;
var curious = require('../curious2.js');

describe('CuriousQuery', function () {
  describe('#query', function () {
    var expectedQuery = (
      'Experiment(id=302), Experiment.reaction_set, '
       + 'Reaction.dataset_set, Dataset.attachment_set'
    );

    // Fake constructor
    function Dataset() {}

    it('should return the empty string with no terms', function () {
      expect((new curious.CuriousQuery()).query()).to.equal('');
    });

    it('should return the correct query string', function () {
      var q = (new curious.CuriousQuery())
        .start('Experiment(id=302)', 'experiments')
        .follow('Experiment.reaction_set', 'reactions')
        .follow('Reaction.dataset_set', 'datasets').wrapWith(Dataset)
        .follow('Dataset.attachment_set', 'attachments');

      expect(q.query()).to.equal(expectedQuery);
    });

    it('should allow shortcuts', function () {
      // Terser version of the same query
      var q = new curious.CuriousQuery('Experiment(id=302)', 'experiment')
        .follow('Experiment.reaction_set', 'reactions')
        .follow('Reaction.dataset_set', 'dataset', Dataset)
        .follow('Dataset.attachment_set', 'attachments');

      expect(q.query()).to.equal(expectedQuery);
    });
  });

  describe('#start', function () {
    var startingTerm = 'Experiment(id=302)';

    // Fake constructor
    function Experiment() { return this; }
    function experimentFactory() { return Object.create(new Experiment()); }

    it('should start the query', function () {
      var q = (new curious.CuriousQuery()).start(startingTerm, 'experiments');

      expect(q.query()).to.equal(startingTerm);
    });

    it('should require both a term and a relationship', function () {
      expect(function () {
        (new curious.CuriousQuery()).start();
      }).to.throw(/term/);

      expect(function () {
        (new curious.CuriousQuery()).start(startingTerm);
      }).to.throw(/relationship/);
    });

    it('should allow custom constructors', function () {
      var q = (new curious.CuriousQuery())
        .start(startingTerm, 'experiments')
        .wrapWith(Experiment);

      expect(q.query()).to.equal(startingTerm);

      expect(q.objectFactories).to.have.length(1);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
    });

    it('should allow function factories', function () {
      var q = (new curious.CuriousQuery())
        .start(startingTerm, 'experiments')
        .wrapDynamically(experimentFactory);

      expect(q.query()).to.equal(startingTerm);

      expect(q.objectFactories).to.have.length(1);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
    });

    it('should allow shortcuts', function () {
      var q = new curious.CuriousQuery(startingTerm, 'experiments', Experiment);
      var q2 = new curious.CuriousQuery(startingTerm, 'experiments', experimentFactory);

      expect(q.query()).to.equal(startingTerm);

      expect(q.objectFactories).to.have.length(1);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);

      expect(q2.objectFactories).to.have.length(1);
      expect(q2.objectFactories[0]()).to.be.an.instanceof(Experiment);
    });
  });

  describe('#follow', function () {
    var expectedQuery = 'Experiment(id=302), Experiment.reaction_set';
    var startingQuery;

    // Fake constructor
    function Experiment() { return this; }
    function Reaction() { return this; }
    function reactionFactory() { return Object.create(new Reaction()); }

    beforeEach(function () {
      startingQuery = new curious.CuriousQuery(
        'Experiment(id=302)', 'experiments', Experiment
      );
    });

    it('should append to the query with a comma', function () {
      var q = startingQuery
        .follow('Experiment.reaction_set', 'reactions');
      expect(q.query()).to.equal(expectedQuery);
    });

    it('should successfully allow terms without commas', function () {
      var q = startingQuery
        .follow('Experiment.reaction_set Reaction.dataset_set', 'datasets');

      expect(q.query()).to.equal(expectedQuery + ' Reaction.dataset_set');
    });

    it('should require both a term and a relationship', function () {
      expect(function () {
        startingQuery.follow();
      }).to.throw(/term/);

      expect(function () {
        startingQuery.follow('Experiment.reaction_set');
      }).to.throw(/relationship/);
    });

    it('should allow custom constructors', function () {
      var q = startingQuery
        .follow('Experiment.reaction_set', 'reactions')
        .wrapWith(Reaction);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(2);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Reaction);
    });

    it('should allow function factories', function () {
      var q = startingQuery
        .follow('Experiment.reaction_set', 'reactions')
        .wrapDynamically(reactionFactory);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(2);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Reaction);
    });

    it('should allow shortcuts', function () {
      var q = startingQuery.clone()
        .follow('Experiment.reaction_set', 'reactions', Reaction);
      var q2 = startingQuery.clone()
        .follow('Experiment.reaction_set', 'reactions', reactionFactory);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(2);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Reaction);

      expect(q2.query()).to.equal(expectedQuery);

      expect(q2.objectFactories).to.have.length(2);
      expect(q2.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q2.objectFactories[1]()).to.be.an.instanceof(Reaction);
    });

  });

  describe('#with', function () {
    var expectedQuery = (
      'Experiment(id=302)'
      + ' ?(Experiment.compounds_of_interest)'
      + ' Experiment.reaction_set'
    );
    var startingQuery;

    // Fake constructor
    function Experiment() { return this; }
    function Reaction() { return this; }
    function Compound() { return this; }
    function compoundFactory() { return Object.create(new Compound()); }

    beforeEach(function () {
      startingQuery = new curious.CuriousQuery(
        'Experiment(id=302)', 'experiments', Experiment
      );
    });

    it('should append to the query with a groupng', function () {
      var q = startingQuery
        .with('Experiment.compounds_of_interest', 'compounds')
        .follow('Experiment.reaction_set', 'reactions');

      expect(q.query()).to.equal(expectedQuery);
    });

    it('should successfully allow terms without commas inside the group', function () {
      var q = startingQuery
        .with('Experiment.compounds_of_interest Compound.standard_set', 'standards')
        .follow('Experiment.reaction_set', 'reactions');

      expect(q.query()).to.equal(
        'Experiment(id=302)'
        + ' ?(Experiment.compounds_of_interest Compound.standard_set)'
        + ' Experiment.reaction_set'
      );
    });

    it('should require both a term and a relationship', function () {
      expect(function () {
        startingQuery.with();
      }).to.throw(/term/);

      expect(function () {
        startingQuery.with('Experiment.reaction_set');
      }).to.throw(/relationship/);
    });

    it('should allow custom constructors', function () {
      var q = startingQuery
        .with('Experiment.compounds_of_interest', 'compounds').wrapWith(Compound)
        .follow('Experiment.reaction_set', 'reactions').wrapWith(Reaction);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(3);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Compound);
      expect(q.objectFactories[2]()).to.be.an.instanceof(Reaction);
    });

    it('should allow function factories', function () {
      var q = startingQuery
        .with('Experiment.compounds_of_interest', 'compounds')
          .wrapDynamically(compoundFactory)
        .follow('Experiment.reaction_set', 'reactions').wrapWith(Reaction);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(3);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Compound);
      expect(q.objectFactories[2]()).to.be.an.instanceof(Reaction);
    });

    it('should allow shortcuts', function () {
      var q = startingQuery.clone()
        .with('Experiment.compounds_of_interest', 'compounds', Compound)
        .follow('Experiment.reaction_set', 'reactions').wrapWith(Reaction);
      var q2 = startingQuery.clone()
        .with('Experiment.compounds_of_interest', 'compounds', compoundFactory)
        .follow('Experiment.reaction_set', 'reactions').wrapWith(Reaction);

      expect(q.query()).to.equal(expectedQuery);

      expect(q.objectFactories).to.have.length(3);
      expect(q.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q.objectFactories[1]()).to.be.an.instanceof(Compound);
      expect(q.objectFactories[2]()).to.be.an.instanceof(Reaction);

      expect(q2.query()).to.equal(expectedQuery);

      expect(q2.objectFactories).to.have.length(3);
      expect(q2.objectFactories[0]()).to.be.an.instanceof(Experiment);
      expect(q2.objectFactories[1]()).to.be.an.instanceof(Compound);
      expect(q2.objectFactories[2]()).to.be.an.instanceof(Reaction);
    });
  });

  // having/notHaving should work basically the same way
  [
    {word: 'having', symbol: '+'},
    {word: 'notHaving', symbol: '-'},
  ].forEach(function (having) {

    describe('#' + having.word, function () {
      var havingClause = 'Experiment.compounds_of_interest(id=123)';
      var expectedQuery = 'Experiment ' + having.symbol + '(' + havingClause + ')';
      var startingQuery;

      beforeEach(function () {
        startingQuery = new curious.CuriousQuery(
          'Experiment', 'experiments'
        );
      });

      it('should append to the query with a "' + having.symbol + '"', function () {
        var q = startingQuery[having.word](havingClause);
        expect(q.query()).to.equal(expectedQuery);
      });

      it('should correctly insert into a query', function () {
        var q = startingQuery[having.word](havingClause)
          .follow('Experiment.reaction_set', 'reactions');
        expect(q.query()).to.equal(expectedQuery + ' Experiment.reaction_set');
      });
    });
  });

});

}());
<|endoftext|>