<commit_before>// memory.js
//
// In-memory storage of data
//
// Copyright 2011,2012 StatusNet Inc.
//
// 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.

var Step = require('step'),
    databank = require('../databank'),
    Databank = databank.Databank,
    DatabankError = databank.DatabankError,
    AlreadyExistsError = databank.AlreadyExistsError,
    NoSuchThingError = databank.NoSuchThingError;

var MemoryDatabank = function(params) {
    this.schema = params.schema || {};
    this.data   = params.data   || {};
};

MemoryDatabank.prototype = new Databank();

MemoryDatabank.prototype.freeze = function(value) {
    var dup, i;

    switch (typeof value) {
    case 'number':
        return value;
        break;
    case 'object':
        if (value instanceof Array) {
            dup = new Array(value.length);
            for (i = 0; i < value.length; i++) {
                dup[i] = this.freeze(value[i]);
            }
            return dup;
        }
        // FALL THROUGH
    default:
        return JSON.stringify(value);
    }
};

MemoryDatabank.prototype.melt = function(value) {
    var dup, i;

    switch (typeof value) {
    case 'string':
        return JSON.parse(value);
        break;
    case 'number':
        return value;
        break;
    case 'object':
        if (value instanceof Array) {
            dup = new Array(value.length);
            for (i = 0; i < value.length; i++) {
                dup[i] = this.melt(value[i]);
            }
            return dup;
        }
        // FALL THROUGH
    default:
        throw new DatabankError("melt() argument not string, number, or array.");
    }
};

MemoryDatabank.prototype.connect = function(params, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        var type;
        bank.types = {};
        for (type in bank.schema) {
            bank.types[type] = {};
        }
        Step(
            function() {
                var key, group = this.group();
                for (type in bank.data) {
                    for (key in bank.data[type]) {
                        bank.create(type, key, bank.data[type][key], group());
                    }
                }
            },
            function(err, created) {
                if (err) {
                    onCompletion(err);
                } else {
                    onCompletion(null);
                }
            }
        );
    });
};

MemoryDatabank.prototype.disconnect = function(onCompletion) {
    var bank = this;
    process.nextTick(function() {
        delete bank.types;
        // Always succeed
        onCompletion(null);
    });
};

MemoryDatabank.prototype.create = function(type, id, value, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (id in bank.types[type]) {
            onCompletion(new AlreadyExistsError(type, id), null);
        } else {
            bank.types[type][id] = bank.freeze(value);
            onCompletion(null, value);
        }
    });
};

MemoryDatabank.prototype.update = function(type, id, value, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else {
            bank.types[type][id] = bank.freeze(value);
            onCompletion(null, value);
        }
    });
};

MemoryDatabank.prototype.read = function(type, id, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        var value;

        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else {
            value = bank.melt(bank.types[type][id]);
            onCompletion(null, value);
        }
    });
};

MemoryDatabank.prototype.del = function(type, id, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id));
        } else {
            delete bank.types[type][id];
            onCompletion(null);
        }
    });
};

MemoryDatabank.prototype.save = function(type, id, value, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        bank.types[type][id] = bank.freeze(value);
        onCompletion(null, value);
    });
};

MemoryDatabank.prototype.search = function(type, criteria, onResult, onCompletion) {
    var bank = this;
    process.nextTick(function() {

        var id, value;

        if (!(type in bank.types)) {
            bank.types[type] = {};
        }

        // FIXME: maybe scanning each and every item isn't
        // the most efficient way to search...?

        for (id in bank.types[type]) {
            value = bank.melt(bank.types[type][id]);
            if (bank.matchesCriteria(value, criteria)) {
                onResult(value);
            }
        }

        onCompletion(null);
    });
};

MemoryDatabank.prototype.readAll = function(type, ids, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        var i, id, value, map = {};
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }

        for (i = 0; i < ids.length; i++) {
            id = ids[i];
            if (!(id in bank.types[type])) {
                map[id] = null;
            } else {
                map[id] = bank.melt(bank.types[type][id]);
            }
        }

        onCompletion(null, map);
    });
};

MemoryDatabank.prototype.incr = function(type, id, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }

        if (!(id in bank.types[type])) {
            bank.types[type][id] = 1;
            onCompletion(null, 1);
        } else {
            bank.types[type][id]++;
            onCompletion(null, bank.types[type][id]);
        }
    });
};

MemoryDatabank.prototype.decr = function(type, id, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            bank.types[type][id] = -1;
            onCompletion(null, -1);
        } else {
            bank.types[type][id]--;
            onCompletion(null, bank.types[type][id]);
        }
    });
};

MemoryDatabank.prototype.append = function(type, id, toAppend, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            bank.types[type][id] = [bank.freeze(toAppend)];
            onCompletion(null, bank.types[type][id]);
        } else {
            bank.types[type][id].push(bank.freeze(toAppend));
            onCompletion(null, bank.types[type][id]);
        }
    });
};

MemoryDatabank.prototype.prepend = function(type, id, toAppend, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            bank.types[type][id] = [bank.freeze(toAppend)];
            onCompletion(null, bank.types[type][id]);
        } else {
            bank.types[type][id].unshift(bank.freeze(toAppend));
            onCompletion(null, bank.types[type][id]);
        }
    });
};

MemoryDatabank.prototype.item = function(type, id, index, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else if (!(index in bank.types[type][id])) {
            onCompletion(new DatabankError("Bad index: " + index), null);
        } else {
            onCompletion(null, bank.melt(bank.types[type][id][index]));
        }
    });
};

MemoryDatabank.prototype.slice = function(type, id, start, length, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else {
            onCompletion(null, bank.melt(bank.types[type][id].slice(start, length)));
        }
    });
};

MemoryDatabank.prototype.indexOf = function(type, id, item, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else {
            onCompletion(null, bank.types[type][id].indexOf(bank.freeze(item)));
        }
    });
};

MemoryDatabank.prototype.remove = function(type, id, item, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        var i;
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else {
            i = bank.types[type][id].indexOf(bank.freeze(item));
            if (i === -1) {
                onCompletion(new DatabankError("No such item"));
            } else {
                bank.types[type][id].splice(i, 1);
                onCompletion(null);
            }
        }
    });
};

exports.MemoryDatabank = MemoryDatabank;
<commit_msg>Make sure bank.types exists<commit_after>// memory.js
//
// In-memory storage of data
//
// Copyright 2011,2012 StatusNet Inc.
//
// 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.

var Step = require('step'),
    databank = require('../databank'),
    Databank = databank.Databank,
    DatabankError = databank.DatabankError,
    AlreadyExistsError = databank.AlreadyExistsError,
    NoSuchThingError = databank.NoSuchThingError;

var MemoryDatabank = function(params) {
    this.schema = params.schema || {};
    this.data   = params.data   || {};
};

MemoryDatabank.prototype = new Databank();

MemoryDatabank.prototype.freeze = function(value) {
    var dup, i;

    switch (typeof value) {
    case 'number':
        return value;
        break;
    case 'object':
        if (value instanceof Array) {
            dup = new Array(value.length);
            for (i = 0; i < value.length; i++) {
                dup[i] = this.freeze(value[i]);
            }
            return dup;
        }
        // FALL THROUGH
    default:
        return JSON.stringify(value);
    }
};

MemoryDatabank.prototype.melt = function(value) {
    var dup, i;

    switch (typeof value) {
    case 'string':
        return JSON.parse(value);
        break;
    case 'number':
        return value;
        break;
    case 'object':
        if (value instanceof Array) {
            dup = new Array(value.length);
            for (i = 0; i < value.length; i++) {
                dup[i] = this.melt(value[i]);
            }
            return dup;
        }
        // FALL THROUGH
    default:
        throw new DatabankError("melt() argument not string, number, or array.");
    }
};

MemoryDatabank.prototype.connect = function(params, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        var type;
        bank.types = {};
        for (type in bank.schema) {
            bank.types[type] = {};
        }
        Step(
            function() {
                var key, group = this.group();
                for (type in bank.data) {
                    for (key in bank.data[type]) {
                        bank.create(type, key, bank.data[type][key], group());
                    }
                }
            },
            function(err, created) {
                if (err) {
                    onCompletion(err);
                } else {
                    onCompletion(null);
                }
            }
        );
    });
};

MemoryDatabank.prototype.disconnect = function(onCompletion) {
    var bank = this;
    process.nextTick(function() {
        delete bank.types;
        // Always succeed
        onCompletion(null);
    });
};

MemoryDatabank.prototype.create = function(type, id, value, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (id in bank.types[type]) {
            onCompletion(new AlreadyExistsError(type, id), null);
        } else {
            bank.types[type][id] = bank.freeze(value);
            onCompletion(null, value);
        }
    });
};

MemoryDatabank.prototype.update = function(type, id, value, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else {
            bank.types[type][id] = bank.freeze(value);
            onCompletion(null, value);
        }
    });
};

MemoryDatabank.prototype.read = function(type, id, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        var value;

        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else {
            value = bank.melt(bank.types[type][id]);
            onCompletion(null, value);
        }
    });
};

MemoryDatabank.prototype.del = function(type, id, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id));
        } else {
            delete bank.types[type][id];
            onCompletion(null);
        }
    });
};

MemoryDatabank.prototype.save = function(type, id, value, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        bank.types[type][id] = bank.freeze(value);
        onCompletion(null, value);
    });
};

MemoryDatabank.prototype.search = function(type, criteria, onResult, onCompletion) {
    var bank = this;
    process.nextTick(function() {

        var id, value;

        if (!bank.types) {
            bank.types = {};
        }

        if (!(type in bank.types)) {
            bank.types[type] = {};
        }

        // FIXME: maybe scanning each and every item isn't
        // the most efficient way to search...?

        for (id in bank.types[type]) {
            value = bank.melt(bank.types[type][id]);
            if (bank.matchesCriteria(value, criteria)) {
                onResult(value);
            }
        }

        onCompletion(null);
    });
};

MemoryDatabank.prototype.readAll = function(type, ids, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        var i, id, value, map = {};

        if (!bank.types) {
            bank.types = {};
        }

        if (!(type in bank.types)) {
            bank.types[type] = {};
        }

        for (i = 0; i < ids.length; i++) {
            id = ids[i];
            if (!(id in bank.types[type])) {
                map[id] = null;
            } else {
                map[id] = bank.melt(bank.types[type][id]);
            }
        }

        onCompletion(null, map);
    });
};

MemoryDatabank.prototype.incr = function(type, id, onCompletion) {
    var bank = this;
    process.nextTick(function() {

        if (!bank.types) {
            bank.types = {};
        }

        if (!(type in bank.types)) {
            bank.types[type] = {};
        }

        if (!(id in bank.types[type])) {
            bank.types[type][id] = 1;
            onCompletion(null, 1);
        } else {
            bank.types[type][id]++;
            onCompletion(null, bank.types[type][id]);
        }
    });
};

MemoryDatabank.prototype.decr = function(type, id, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            bank.types[type][id] = -1;
            onCompletion(null, -1);
        } else {
            bank.types[type][id]--;
            onCompletion(null, bank.types[type][id]);
        }
    });
};

MemoryDatabank.prototype.append = function(type, id, toAppend, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            bank.types[type][id] = [bank.freeze(toAppend)];
            onCompletion(null, bank.types[type][id]);
        } else {
            bank.types[type][id].push(bank.freeze(toAppend));
            onCompletion(null, bank.types[type][id]);
        }
    });
};

MemoryDatabank.prototype.prepend = function(type, id, toAppend, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            bank.types[type][id] = [bank.freeze(toAppend)];
            onCompletion(null, bank.types[type][id]);
        } else {
            bank.types[type][id].unshift(bank.freeze(toAppend));
            onCompletion(null, bank.types[type][id]);
        }
    });
};

MemoryDatabank.prototype.item = function(type, id, index, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else if (!(index in bank.types[type][id])) {
            onCompletion(new DatabankError("Bad index: " + index), null);
        } else {
            onCompletion(null, bank.melt(bank.types[type][id][index]));
        }
    });
};

MemoryDatabank.prototype.slice = function(type, id, start, length, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else {
            onCompletion(null, bank.melt(bank.types[type][id].slice(start, length)));
        }
    });
};

MemoryDatabank.prototype.indexOf = function(type, id, item, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else {
            onCompletion(null, bank.types[type][id].indexOf(bank.freeze(item)));
        }
    });
};

MemoryDatabank.prototype.remove = function(type, id, item, onCompletion) {
    var bank = this;
    process.nextTick(function() {
        var i;
        if (!bank.types) {
            bank.types = {};
        }
        if (!(type in bank.types)) {
            bank.types[type] = {};
        }
        if (!(id in bank.types[type])) {
            onCompletion(new NoSuchThingError(type, id), null);
        } else {
            i = bank.types[type][id].indexOf(bank.freeze(item));
            if (i === -1) {
                onCompletion(new DatabankError("No such item"));
            } else {
                bank.types[type][id].splice(i, 1);
                onCompletion(null);
            }
        }
    });
};

exports.MemoryDatabank = MemoryDatabank;
<|endoftext|>


<commit_before>/*jshint node:true*/
var http = require('http');
module.exports.proxy = function(req, res, server, port){

    var options = {};

    options = {
        hostname: server,
        port: port,
        method: req.method,
        path: req.path,
        headers: {}
    };

    if ( req.headers['content-length'] ){
        options.headers['content-length'] = req.headers['content-length'];
    }

    if ( req.headers['content-type'] ){
        options.headers['content-type'] = req.headers['content-type'];
    }

    var callback = function(response) {

        res.writeHead(response.statusCode, response.headers);
        response.on('data', function (chunk) {
            res.write(chunk);
        });
        response.on('end', function() {
            res.end();
        });

    };

    var request = http.request(options, callback);
    req.on('data', function (chunk) {
        request.write(chunk);
    });
    req.on('end', function() {
        request.end();
    });

}<commit_msg>send all headers to server.<commit_after>/*jshint node:true*/
var http = require('http');
module.exports.proxy = function(req, res, server, port){

    var options = {};

    options = {
        hostname: server,
        port: port,
        method: req.method,
        path: req.path,
        headers: {}
    };

    options.headers = req.headers;

    var callback = function(response) {

        res.writeHead(response.statusCode, response.headers);
        response.on('data', function (chunk) {
            res.write(chunk);
        });
        response.on('end', function() {
            res.end();
        });

    };

    var request = http.request(options, callback);
    req.on('data', function (chunk) {
        request.write(chunk);
    });
    req.on('end', function() {
        request.end();
    });

}<|endoftext|>


<commit_before>'use strict';

/**
 * @module e2e
 */

/**
 * A web page to help writing end to end tests with protractor for OpenVeo.
 *
 * Do not use this directly but extend it.
 *
 * @example
 *
 *     var Page = require('@openveo/test').e2e.Page;
 *
 *     function MyPage() {
 *       MyPage.super_.call(this);
 *       this.path = 'be/myPage';
 *     }
 *
 *     module.exports = MyPage;
 *     util.inherits(MyPage, Page);
 *
 *     var page = new MyPage();
 *     page.load().then(function() {
 *       console.log('Page fully loaded');
 *     });
 *
 * @class Page
 * @constructor
 */
function Page() {

  /**
   * Protractor expected conditions.
   *
   * @property EC
   * @type ExpectedConditions
   */
  this.EC = protractor.ExpectedConditions;

  /**
   * Protractor control flow.
   *
   * @property flow
   * @type ControlFlow
   */
  this.flow = browser.controlFlow();

  /**
   * Body element.
   *
   * @property bodyElement
   * @type ElementFinder
   */
  this.bodyElement = element(by.css('body'));

  /**
   * Page element.
   *
   * Page wrapper holding the content scrollbar.
   *
   * @property pageElement
   * @type ElementFinder
   */
  this.pageElement = element(by.id('page-content-wrapper'));
}

module.exports = Page;

/**
 * Loads the page.
 *
 * @example
 *
 *     var Page = require('@openveo/test').e2e.Page;
 *
 *     function MyPage() {
 *       MyPage.super_.call(this);
 *       this.path = 'be/myPage';
 *     }
 *
 *     module.exports = MyPage;
 *     util.inherits(MyPage, Page);
 *
 *     var page = new MyPage();
 *     page.load().then(function() {
 *       console.log('Page fully loaded');
 *     });
 *
 * @method load
 * @return {Promise} Promise resolving when the page is fully loaded
 */
Page.prototype.load = function() {
  var self = this;
  var expectedUrl = process.protractorConf.baseUrl + this.path;

  // Load url of the page
  return browser.get(this.path).then(function() {

    // Deactivate animations
    self.bodyElement.allowAnimations(false);

    // Verify if loaded page is the expected one
    return browser.getCurrentUrl().then(function(currentUrl) {
      if (currentUrl.replace(/\/$/, '') !== expectedUrl.replace(/\/$/, ''))
        return protractor.promise.rejected(new Error('Failed loading page ' + expectedUrl +
                                                     ' (got ' + currentUrl + ')'));
      else
        return self.onLoaded();
    });

  }).then(function() {
    return protractor.promise.fulfilled();
  });

};

/**
 * Gets page title as described by the HTMLTitleElement.
 *
 * @example
 *
 *     // With MyPage extending Page
 *     var page = new MyPage();
 *     assert.eventually.equal(page.getTitle(), 'My page title');
 *
 * @method getTitle
 * @return {Promise} Promise resolving with the title of the page
 */
Page.prototype.getTitle = function() {
  return browser.getTitle();
};

/**
 * Removes all cookies on the actual page.
 *
 * @method deleteCookies
 * @return {Promise} Promise resolving when all cookies are deleted
 */
Page.prototype.deleteCookies = function() {
  return browser.driver.manage().deleteAllCookies();
};

/**
 * Sends an http request and return its reponse.
 *
 * This will execute the request from the page.
 *
 * @param {String} path Request's path
 * @param {String} method HTTP method to use
 * @param {Object} data Request's data to send in body
 * @return {Promise} Promise resolving with the request's response
 */
Page.prototype.sendRequest = function(path, method, data) {
  var url = process.protractorConf.baseUrl + path;

  return browser.executeAsyncScript(function() {
    var callback = arguments[arguments.length - 1];
    var url = arguments[0];
    var method = arguments[1];
    var data = arguments[2];
    var $http = angular.injector(['ng']).get('$http');
    $http({
      url: url,
      method: method,
      data: data,
      responseType: 'json'
    }).then(function(response) {
      callback(response);
    }, function(response) {
      callback(response);
    });
  }, url, method, data);
};

/**
 * Refreshes actual page.
 *
 * @method refresh
 * @return {Promise} Promise resolving when the page is fully loaded
 */
Page.prototype.refresh = function() {
  var self = this;

  return browser.refresh().then(function() {
    self.bodyElement.allowAnimations(false);
    return self.onLoaded();
  }).then(function() {
    return protractor.promise.fulfilled();
  });
};

/**
 * Handles page loaded.
 *
 * Use this method to perform actions after the page is loaded. Typically, verify that the page is loaded by
 * waiting for elements to be present on the page.
 *
 * By default it does nothing, override it to define your own behaviour.
 *
 * @method onLoaded
 * @return {Promise} Promise resolving when the page is fully loaded
 */
Page.prototype.onLoaded = function() {};
<commit_msg>Add function to get current path without host<commit_after>'use strict';

var url = require('url');

/**
 * @module e2e
 */

/**
 * A web page to help writing end to end tests with protractor for OpenVeo.
 *
 * Do not use this directly but extend it.
 *
 * @example
 *
 *     var Page = require('@openveo/test').e2e.Page;
 *
 *     function MyPage() {
 *       MyPage.super_.call(this);
 *       this.path = 'be/myPage';
 *     }
 *
 *     module.exports = MyPage;
 *     util.inherits(MyPage, Page);
 *
 *     var page = new MyPage();
 *     page.load().then(function() {
 *       console.log('Page fully loaded');
 *     });
 *
 * @class Page
 * @constructor
 */
function Page() {

  /**
   * Protractor expected conditions.
   *
   * @property EC
   * @type ExpectedConditions
   */
  this.EC = protractor.ExpectedConditions;

  /**
   * Protractor control flow.
   *
   * @property flow
   * @type ControlFlow
   */
  this.flow = browser.controlFlow();

  /**
   * Body element.
   *
   * @property bodyElement
   * @type ElementFinder
   */
  this.bodyElement = element(by.css('body'));

  /**
   * Page element.
   *
   * Page wrapper holding the content scrollbar.
   *
   * @property pageElement
   * @type ElementFinder
   */
  this.pageElement = element(by.id('page-content-wrapper'));
}

module.exports = Page;

/**
 * Loads the page.
 *
 * @example
 *
 *     var Page = require('@openveo/test').e2e.Page;
 *
 *     function MyPage() {
 *       MyPage.super_.call(this);
 *       this.path = 'be/myPage';
 *     }
 *
 *     module.exports = MyPage;
 *     util.inherits(MyPage, Page);
 *
 *     var page = new MyPage();
 *     page.load().then(function() {
 *       console.log('Page fully loaded');
 *     });
 *
 * @method load
 * @return {Promise} Promise resolving when the page is fully loaded
 */
Page.prototype.load = function() {
  var self = this;
  var expectedUrl = process.protractorConf.baseUrl + this.path;

  // Load url of the page
  return browser.get(this.path).then(function() {

    // Deactivate animations
    self.bodyElement.allowAnimations(false);

    // Verify if loaded page is the expected one
    return browser.getCurrentUrl().then(function(currentUrl) {
      if (currentUrl.replace(/\/$/, '') !== expectedUrl.replace(/\/$/, ''))
        return protractor.promise.rejected(new Error('Failed loading page ' + expectedUrl +
                                                     ' (got ' + currentUrl + ')'));
      else
        return self.onLoaded();
    });

  }).then(function() {
    return protractor.promise.fulfilled();
  });

};

/**
 * Gets page title as described by the HTMLTitleElement.
 *
 * @example
 *
 *     // With MyPage extending Page
 *     var page = new MyPage();
 *     assert.eventually.equal(page.getTitle(), 'My page title');
 *
 * @method getTitle
 * @return {Promise} Promise resolving with the title of the page
 */
Page.prototype.getTitle = function() {
  return browser.getTitle();
};

/**
 * Removes all cookies on the actual page.
 *
 * @method deleteCookies
 * @return {Promise} Promise resolving when all cookies are deleted
 */
Page.prototype.deleteCookies = function() {
  return browser.driver.manage().deleteAllCookies();
};

/**
 * Sends an http request and return its reponse.
 *
 * This will execute the request from the page.
 *
 * @param {String} path Request's path
 * @param {String} method HTTP method to use
 * @param {Object} data Request's data to send in body
 * @return {Promise} Promise resolving with the request's response
 */
Page.prototype.sendRequest = function(path, method, data) {
  var url = process.protractorConf.baseUrl + path;

  return browser.executeAsyncScript(function() {
    var callback = arguments[arguments.length - 1];
    var url = arguments[0];
    var method = arguments[1];
    var data = arguments[2];
    var $http = angular.injector(['ng']).get('$http');
    $http({
      url: url,
      method: method,
      data: data,
      responseType: 'json'
    }).then(function(response) {
      callback(response);
    }, function(response) {
      callback(response);
    });
  }, url, method, data);
};

/**
 * Refreshes actual page.
 *
 * @method refresh
 * @return {Promise} Promise resolving when the page is fully loaded
 */
Page.prototype.refresh = function() {
  var self = this;

  return browser.refresh().then(function() {
    self.bodyElement.allowAnimations(false);
    return self.onLoaded();
  }).then(function() {
    return protractor.promise.fulfilled();
  });
};

/**
 * Handles page loaded.
 *
 * Use this method to perform actions after the page is loaded. Typically, verify that the page is loaded by
 * waiting for elements to be present on the page.
 *
 * By default it does nothing, override it to define your own behaviour.
 *
 * @method onLoaded
 * @return {Promise} Promise resolving when the page is fully loaded
 */
Page.prototype.onLoaded = function() {};

/**
 * Helper Url
 * Get only current url path without host
 *
 * @method getPath
 * @return {Promise} Promise resolving with current path
 */
Page.prototype.getPath = function() {
  return browser.getCurrentUrl().then(function(urlToParse) {
    var urlParsed = url.parse(urlToParse);
    return protractor.promise.fulfilled(urlParsed.path);
  });
};
<|endoftext|>


<commit_before>/*global jsobj, document */
/*jslint plusplus: true */

(function () {
	'use strict';

	var grid = new jsobj.Grid(),
		disp, rept;

	// difficult -- solved with rule last-in-group
	/*
	grid.addSeeds([
		[  ,  ,  ,  ,  , 1,  , 8,  ],
		[ 8,  ,  , 5, 3,  ,  ,  ,  ],
		[  ,  , 6,  , 2,  , 4,  ,  ],
		[ 6,  ,  , 3,  , 9,  , 7,  ],
		[  , 3, 8,  ,  ,  , 2, 1,  ],
		[  , 1,  , 8,  , 2,  ,  , 3],
		[  ,  , 9,  , 8,  , 5,  ,  ],
		[  ,  ,  ,  , 7, 3,  ,  , 4],
		[  , 7,  , 1,  ,  ,  ,  ,  ]
	]);
	*/

	// diabolical 1	-- solved with rules last-in-group and restricted-possible-value
	/*
	grid.addSeeds([
		[ 7,  ,  ,  , 9, 6,  ,  ,  ],
		[ 8, 9,  ,  ,  , 5, 7,  ,  ],
		[  , 6,  ,  ,  ,  ,  ,  , 2],
		[ 1,  ,  ,  ,  ,  ,  ,  ,  ],
		[  ,  , 4, 1,  , 7, 5,  ,  ],
		[  ,  ,  ,  ,  ,  ,  ,  , 6],
		[ 9,  ,  ,  ,  ,  ,  , 2,  ],
		[  ,  , 8, 9,  ,  ,  , 5, 1],
		[  ,  ,  , 2, 3,  ,  ,  , 8]
	]);
	*/

	/*
	// diabolical 2	-- solved with rules last-in-group and restricted-possible-value
	grid.addSeeds([
		[ 9,  , 4,  ,  , 1,  ,  ,  ],
		[  , 2,  ,  ,  , 3, 7, 1,  ],
		[  ,  ,  ,  , 2,  , 9,  ,  ],
		[ 2,  ,  ,  ,  , 6,  ,  , 4],
		[  , 9,  ,  ,  ,  ,  , 6,  ],
		[ 5,  ,  , 2,  ,  ,  ,  , 7],
		[  ,  , 5,  , 6,  ,  ,  ,  ],
		[  , 8, 9, 5,  ,  ,  , 3,  ],
		[  ,  ,  , 4,  ,  , 5,  , 8]
	]);
	*/

	/*
	// hard 3 - web sudoku -- solved after adding "pairs" rule
	grid.addSeeds([
		[ 8,  , 1, 7,  ,  , 3, 9,  ],
		[  ,  ,  ,  ,  , 2, 4,  ,  ],
		[ 4,  ,  ,  , 9,  ,  , 8,  ],
		[  ,  , 5,  ,  , 8,  ,  ,  ],
		[ 3,  ,  ,  , 6,  ,  ,  , 9],
		[  ,  ,  , 2,  ,  , 8,  ,  ],
		[  , 1,  ,  , 7,  ,  ,  , 5],
		[  ,  , 3, 6,  ,  ,  ,  ,  ],
		[  , 2, 7,  ,  , 9, 6,  , 3]
	]);
	*/

	/*
	// evil 4 - websudoku.com -- solved with pairs rule
	grid.addSeeds([
		[  ,  ,  ,  , 2,  , 7,  ,  ],
		[  , 2,  ,  ,  ,  ,  ,  , 6],
		[  , 8,  , 5,  , 9,  ,  ,  ],
		[  ,  , 2,  , 9,  ,  , 6, 1],
		[  ,  , 8, 1,  , 7, 9,  ,  ],
		[ 9, 1,  ,  , 6,  , 8,  ,  ],
		[  ,  ,  , 7,  , 6,  , 1,  ],
		[ 5,  ,  ,  ,  ,  ,  , 7,  ],
		[  ,  , 4,  , 3,  ,  ,  ,  ]
	]);
	*/

	// evil 5 - websudoku.com --
	grid.addSeeds([
		[ 3,  ,  ,  ,  , 9,  ,  ,  ],
		[  , 5,  ,  , 7,  , 8, 6,  ],
		[  , 6,  ,  ,  ,  ,  , 2, 7],
		[  , 4,  , 9,  , 5,  ,  , 8],
		[  ,  ,  ,  ,  ,  ,  ,  ,  ],
		[ 7,  ,  , 2,  , 6,  , 4,  ],
		[ 4, 2,  ,  ,  ,  ,  , 9,  ],
		[  , 1, 8,  , 9,  ,  , 5,  ],
		[  ,  ,  , 5,  ,  ,  ,  , 1]
	]);

	grid.solve();
	disp = new jsobj.views.StaticGrid(grid);
	rept = new jsobj.views.Report(grid);

}());
<commit_msg>add attempted grid to test last-in-group rule, not working<commit_after>/*global jsobj, document */
/*jslint plusplus: true */

(function () {
	'use strict';

	var grid = new jsobj.Grid(),
		disp,
		rept;

	// difficult -- solved with rule last-in-group
	/*
	grid.addSeeds([
		[  ,  ,  ,  ,  , 1,  , 8,  ],
		[ 8,  ,  , 5, 3,  ,  ,  ,  ],
		[  ,  , 6,  , 2,  , 4,  ,  ],
		[ 6,  ,  , 3,  , 9,  , 7,  ],
		[  , 3, 8,  ,  ,  , 2, 1,  ],
		[  , 1,  , 8,  , 2,  ,  , 3],
		[  ,  , 9,  , 8,  , 5,  ,  ],
		[  ,  ,  ,  , 7, 3,  ,  , 4],
		[  , 7,  , 1,  ,  ,  ,  ,  ]
	]);
	*/

	// diabolical 1	-- solved with rules last-in-group and restricted-possible-value
	/*
	grid.addSeeds([
		[ 7,  ,  ,  , 9, 6,  ,  ,  ],
		[ 8, 9,  ,  ,  , 5, 7,  ,  ],
		[  , 6,  ,  ,  ,  ,  ,  , 2],
		[ 1,  ,  ,  ,  ,  ,  ,  ,  ],
		[  ,  , 4, 1,  , 7, 5,  ,  ],
		[  ,  ,  ,  ,  ,  ,  ,  , 6],
		[ 9,  ,  ,  ,  ,  ,  , 2,  ],
		[  ,  , 8, 9,  ,  ,  , 5, 1],
		[  ,  ,  , 2, 3,  ,  ,  , 8]
	]);
	*/

	/*
	// diabolical 2	-- solved with rules last-in-group and restricted-possible-value
	grid.addSeeds([
		[ 9,  , 4,  ,  , 1,  ,  ,  ],
		[  , 2,  ,  ,  , 3, 7, 1,  ],
		[  ,  ,  ,  , 2,  , 9,  ,  ],
		[ 2,  ,  ,  ,  , 6,  ,  , 4],
		[  , 9,  ,  ,  ,  ,  , 6,  ],
		[ 5,  ,  , 2,  ,  ,  ,  , 7],
		[  ,  , 5,  , 6,  ,  ,  ,  ],
		[  , 8, 9, 5,  ,  ,  , 3,  ],
		[  ,  ,  , 4,  ,  , 5,  , 8]
	]);
	*/

	/*
	// hard 3 - web sudoku -- solved after adding "pairs" rule
	grid.addSeeds([
		[ 8,  , 1, 7,  ,  , 3, 9,  ],
		[  ,  ,  ,  ,  , 2, 4,  ,  ],
		[ 4,  ,  ,  , 9,  ,  , 8,  ],
		[  ,  , 5,  ,  , 8,  ,  ,  ],
		[ 3,  ,  ,  , 6,  ,  ,  , 9],
		[  ,  ,  , 2,  ,  , 8,  ,  ],
		[  , 1,  ,  , 7,  ,  ,  , 5],
		[  ,  , 3, 6,  ,  ,  ,  ,  ],
		[  , 2, 7,  ,  , 9, 6,  , 3]
	]);
	*/

	/*
	// evil 4 - websudoku.com -- solved with pairs rule
	grid.addSeeds([
		[  ,  ,  ,  , 2,  , 7,  ,  ],
		[  , 2,  ,  ,  ,  ,  ,  , 6],
		[  , 8,  , 5,  , 9,  ,  ,  ],
		[  ,  , 2,  , 9,  ,  , 6, 1],
		[  ,  , 8, 1,  , 7, 9,  ,  ],
		[ 9, 1,  ,  , 6,  , 8,  ,  ],
		[  ,  ,  , 7,  , 6,  , 1,  ],
		[ 5,  ,  ,  ,  ,  ,  , 7,  ],
		[  ,  , 4,  , 3,  ,  ,  ,  ]
	]);
	*/

	/*
	// evil 5 - websudoku.com --
	grid.addSeeds([
		[ 3,  ,  ,  ,  , 9,  ,  ,  ],
		[  , 5,  ,  , 7,  , 8, 6,  ],
		[  , 6,  ,  ,  ,  ,  , 2, 7],
		[  , 4,  , 9,  , 5,  ,  , 8],
		[  ,  ,  ,  ,  ,  ,  ,  ,  ],
		[ 7,  ,  , 2,  , 6,  , 4,  ],
		[ 4, 2,  ,  ,  ,  ,  , 9,  ],
		[  , 1, 8,  , 9,  ,  , 5,  ],
		[  ,  ,  , 5,  ,  ,  ,  , 1]
	]);
	*/

	// rule test
	/*
	grid.addSeeds([
		[  ,  ,  , 4, 5, 6, 7, 8, 9],
		[  ,  ,  , 1, 2,  ,  ,  ,  ],
		[  ,  ,  ,  ,  ,  , 1, 2,  ],
		[  , 1,  ,  ,  ,  ,  ,  ,  ],
		[ 2,  ,  ,  ,  ,  ,  ,  ,  ],
		[  ,  ,  ,  ,  ,  ,  ,  ,  ],
		[  ,  , 1,  ,  ,  ,  ,  ,  ],
		[  ,  , 2,  ,  ,  ,  ,  ,  ],
		[  , 3,  ,  ,  ,  ,  ,  ,  ]
	]);
	*/

	//grid.solve();
	jsobj.rules.lastInGroup(grid);
	disp = new jsobj.views.StaticGrid(grid);
	rept = new jsobj.views.Report(grid);

}());
<|endoftext|>


<commit_before>/*
    Ecrire une fonction "shoppingList",
    qui prend un paramètre un tableau de paniers;

    Un panier est un tableau de mots;

    La fonction retourne un tableau d'objet contenant:
        - comme clef le nom du produit rencontré
        - comme valeur le nombre de fois qu'il à été rencontré

    Important -> l'ordre n'a aucune importance
*/

/*      Test 1
    Appel à la fonction "shoppingList",
    prenant en paramètre le tableau

    [
        ["orange", "orange", "kiwi", "ananas"],
        ["kiwi", "ananas", "banane", "prune"],
        ["orange", "orange", "orange", "orange"],
        ["orange", "orange", "kiwi", "kiwi"],
        ["prune", "banane", "pamplemousse", "ananas"]
    ]

    et nous attendons comme résultat

    [{
        "orange": 8,
        "kiwi": 4,
        "ananas": 3,
        "prune": 2,
        "banane": 2,
        "pamplemousse": 1
    }]

*/

shoppingList([
    ["orange", "orange", "kiwi", "ananas"],
    ["kiwi", "ananas", "banane", "prune"],
    ["orange", "orange", "orange", "orange"],
    ["orange", "orange", "kiwi", "kiwi"],
    ["prune", "banane", "pamplemousse", "ananas"]
]);

//  écrire votre code sous ce commentaire
<commit_msg>Update exercice<commit_after>/*
    Ecrire une fonction "shoppingList",
    qui prend un paramètre un tableau de paniers;

    Un panier est un tableau de mots;

    La fonction retourne un objet contenant:
        - comme clef le nom du produit rencontré
        - comme valeur le nombre de fois qu'il à été rencontré

    Important -> l'ordre n'a aucune importance
*/

/*      Test 1
    Appel à la fonction "shoppingList",
    prenant en paramètre le tableau

    [
        ["orange", "orange", "kiwi", "ananas"],
        ["kiwi", "ananas", "banane", "prune"],
        ["orange", "orange", "orange", "orange"],
        ["orange", "orange", "kiwi", "kiwi"],
        ["prune", "banane", "pamplemousse", "ananas"]
    ]

    et nous attendons comme résultat

    {
        "orange": 8,
        "kiwi": 4,
        "ananas": 3,
        "prune": 2,
        "banane": 2,
        "pamplemousse": 1
    }

*/

shoppingList([
    ["orange", "orange", "kiwi", "ananas"],
    ["kiwi", "ananas", "banane", "prune"],
    ["orange", "orange", "orange", "orange"],
    ["orange", "orange", "kiwi", "kiwi"],
    ["prune", "banane", "pamplemousse", "ananas"]
]);

//  écrire votre code sous ce commentaire
<|endoftext|>


<commit_before>var OpenSpending = OpenSpending || {}

OpenSpending.EntriesSearch = function (input, searchResults, template, pageSize, maxPages) {
  window.onhashchange = function () {
    var params = _getParams();
    if (!params['q']) { return; }

    input.val(params['q']);
    _search(params);
  };
  window.onhashchange();

  input.closest('form').submit(function (evt) {
    _extendParams({'q': input.val(), 'page': 1});

    evt.preventDefault();
  });

  function _getParams() {
    var hash = window.location.hash,
        params = {};

    var paramsArray = hash.replace('#', '').split('&');
    if (paramsArray[0] === '') { return params; }

    for (i in paramsArray) {
      var keyValue = paramsArray[i].split('=');
      params[keyValue[0]] = decodeURIComponent(keyValue[1]);
    }

    return params;
  };

  function _extendParams(newAttributes) {
    var newParams = $.extend(_getParams(), newAttributes);

    window.location.hash = _paramsToHash(newParams);

    return newParams;
  };

  function _paramsToHash(params) {
    var values = [];

    for (key in params) {
      values = values.concat(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]));
    }

    return values.join('&');
  };

  function _search(params) {
    var defaultParams = { 'pagesize': pageSize, 'order': 'time:desc' };

    params = $.extend(defaultParams, params);

    _toggleSpinner();

    $.getJSON("/api/2/search", params, function (data) {
      _toggleSpinner();

      if (data.results.length === 0) {
        searchResults.html('No data available for this query.');
        return;
      }

      _displayResults(data, searchResults);
      searchResults.highlight(params['q']);
    });
  };

  function _displayResults(data, element) {
    element.html('');

    for (i in data.results) {
      element.append(_prepareResult(data.results[i]));
    }

    _displayPagination(data.stats.results_count_query, element);
  };

  function _displayPagination(resultsNumber, element) {
    var paginationDiv = $('
');

    _displayPaginationPages(resultsNumber, paginationDiv);
    _displayPaginationMessage(resultsNumber, paginationDiv);

    element.append(paginationDiv);
  };

  function _displayPaginationPages(resultsNumber, element) {
    var pagesCount = Math.ceil(resultsNumber / pageSize),
        pagesDiv = $('
'),
        pagesLinks = $('
'),
        maxPagesHalf = Math.floor(maxPages / 2),
        currentPage = _currentPage(),
        startingPage,
        endingPage;

    if (pagesCount < maxPages) {
      startingPage = 1;
      endingPage = pagesCount;
    }
    else if (currentPage <= maxPagesHalf) {
      startingPage = 1;
      endingPage = maxPages;
    }
    else if (currentPage >= (pagesCount - maxPagesHalf)) {
      startingPage = pagesCount - maxPages + 1;
      endingPage = pagesCount;
    }
    else {
      startingPage = currentPage - Math.ceil(maxPages / 2) + 1;
      endingPage = startingPage + maxPages - 1;
    }

    for (var i = startingPage; i <= endingPage; i++) {
      var pageLink = $('
'+i+'
');

      if (currentPage === i) { pageLink.addClass('active'); }

      pagesLinks.append(pageLink);
    }

    pagesDiv.append(pagesLinks);
    element.append(pagesDiv);

    _setupPaginationEvents(pagesLinks);
  };

  function _currentPage() {
    return parseInt(_getParams()['page']) || 1;
  };

  function _setupPaginationEvents(element) {
    element.children().click(function (evt) {
      var page = $(this).children('a').html();
      _extendParams({'page': page})

      evt.preventDefault();
    });
  };

  function _displayPaginationMessage(resultsNumber, element) {
    var fromResult = 1 + pageSize * (_currentPage() - 1),
        toResult = Math.min(resultsNumber, fromResult + pageSize - 1),
        message = 'Showing '+fromResult+' to '+toResult+' of '+resultsNumber+' entries',
        messageDiv = $('
').html(message);

    element.append(messageDiv);
  };

  function _toggleSpinner(element) {
    input.toggleClass('spinner');
  };

  function _prepareResult(result) {
    console.log(result);
    var titleTemplate = result.dataset.serp_title || $('#search-result-title-template').html();
    result._title = Handlebars.compile(titleTemplate)(result);
    var teaserTemplate = result.dataset.serp_teaser || $('#search-result-teaser-template').html();
    result._teaser = Handlebars.compile(teaserTemplate)(result);
    result.amount = OpenSpending.Utils.formatAmountWithCommas(result.amount, 0,
      result.dataset.currency)
    return template(result);
  };

};

$(document).ready(function () {
  var template = $('#search-result-template').html(),
      resultTemplate = Handlebars.compile(template),
      searchInput = $('#search input[name="q"]'),
      searchResults = $('#search-results'),
      pageSize = 15,
      maxPages = 15;

  OpenSpending.EntriesSearch(searchInput, searchResults, resultTemplate, pageSize, maxPages)
});

<commit_msg>Integration for global search <commit_after>var OpenSpending = OpenSpending || {}

OpenSpending.EntriesSearch = function (input, categories, searchResults, template, pageSize, maxPages) {
  window.onhashchange = function () {
    var params = _getParams();
    if (!params['q']) { return; }

    input.val(params['q']);
    categories.filter('[value='+params['category']+']').attr('checked', true);
    _search(params);
  };
  window.onhashchange();

  input.closest('form').submit(function (evt) {
    _extendParams({'q': input.val(),
                   'category': categories.filter(':checked').val(),
                   'page': 1});

    evt.preventDefault();
  });

  function _getParams() {
    var hash = window.location.hash.substring(1),
        query = location.search.substring(1),
        params = {};

    var paramsArray = query.split('&').concat(hash.split('&'));

    for (i in paramsArray) {
      var keyValue = paramsArray[i].split('=');
      if (keyValue[0].length>0) {
        params[keyValue[0]] = decodeURIComponent(keyValue[1]);
      }
    }

    console.log(params);
    return params;
  };

  function _extendParams(newAttributes) {
    var newParams = $.extend(_getParams(), newAttributes);

    window.location.hash = _paramsToHash(newParams);

    return newParams;
  };

  function _paramsToHash(params) {
    var values = [];

    for (key in params) {
      values = values.concat(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]));
    }

    return values.join('&');
  };

  function _search(params) {
    var defaultParams = { 'pagesize': pageSize, 'order': 'amount:desc' };

    params = $.extend(defaultParams, params);

    _toggleSpinner();

    $.getJSON("/api/2/search", params, function (data) {
      _toggleSpinner();

      if (data.results.length === 0) {
        searchResults.html('
No data available for this query.
');
        return;
      }

      _displayResults(data, searchResults);
      searchResults.highlight(params['q']);
    });
  };

  function _displayResults(data, element) {
    element.html('');

    for (i in data.results) {
      element.append(_prepareResult(data.results[i]));
    }

    _displayPagination(data.stats.results_count_query, element);
  };

  function _displayPagination(resultsNumber, element) {
    var paginationDiv = $('
');

    _displayPaginationPages(resultsNumber, paginationDiv);
    var infoEl = $('#pagination-info');
    _displayPaginationMessage(resultsNumber, infoEl);

    element.append(paginationDiv);
  };

  function _displayPaginationPages(resultsNumber, element) {
    var pagesCount = Math.ceil(resultsNumber / pageSize),
        pagesDiv = $('
'),
        pagesLinks = $('
'),
        maxPagesHalf = Math.floor(maxPages / 2),
        currentPage = _currentPage(),
        startingPage,
        endingPage;

    if (pagesCount < maxPages) {
      startingPage = 1;
      endingPage = pagesCount;
    }
    else if (currentPage <= maxPagesHalf) {
      startingPage = 1;
      endingPage = maxPages;
    }
    else if (currentPage >= (pagesCount - maxPagesHalf)) {
      startingPage = pagesCount - maxPages + 1;
      endingPage = pagesCount;
    }
    else {
      startingPage = currentPage - Math.ceil(maxPages / 2) + 1;
      endingPage = startingPage + maxPages - 1;
    }

    for (var i = startingPage; i <= endingPage; i++) {
      var pageLink = $('
'+i+'
');

      if (currentPage === i) { pageLink.addClass('active'); }

      pagesLinks.append(pageLink);
    }

    pagesDiv.append(pagesLinks);
    element.append(pagesDiv);

    _setupPaginationEvents(pagesLinks);
  };

  function _currentPage() {
    return parseInt(_getParams()['page']) || 1;
  };

  function _setupPaginationEvents(element) {
    element.children().click(function (evt) {
      var page = $(this).children('a').html();
      _extendParams({'page': page})

      evt.preventDefault();
    });
  };

  function _displayPaginationMessage(resultsNumber, element) {
    var fromResult = 1 + pageSize * (_currentPage() - 1),
        toResult = Math.min(resultsNumber, fromResult + pageSize - 1),
        message = 'Showing '+fromResult+' to '+toResult+' of '+resultsNumber+' entries',
        messageDiv = $('
').html(message);

    element.empty();
    element.append(messageDiv);
  };

  function _toggleSpinner(element) {
    input.toggleClass('spinner');
  };

  function _prepareResult(result) {
    var titleTemplate = result.dataset.serp_title || $('#search-result-title-template').html();
    result._title = Handlebars.compile(titleTemplate)(result);
    var teaserTemplate = result.dataset.serp_teaser || $('#search-result-teaser-template').html();
    result._teaser = Handlebars.compile(teaserTemplate)(result);
    result.amount = OpenSpending.Utils.formatAmountWithCommas(result.amount, 0,
      result.dataset.currency)
    return template(result);
  };

};

$(document).ready(function () {
  var template = $('#search-result-template').html(),
      resultTemplate = Handlebars.compile(template),
      searchInput = $('#search input[name="q"]'),
      categories = $('#search .select-category'),
      searchResults = $('#search-results'),
      pageSize = 15,
      maxPages = 15;

  OpenSpending.EntriesSearch(searchInput, categories, searchResults, resultTemplate, pageSize, maxPages)
});

<|endoftext|>


<commit_before>'use strict';
// all the functions in here should be generic - no platform specific code in here!
var mongoose = require('mongoose'),
    Post = mongoose.model('Post'),
    moment = require('moment'),
    config = require('./config');

function unitToMilliseconds(unitString, num) {
    var returnDate = moment();
    switch (unitString) {
    case "y":
        unitString="years";
        break;
    case "m":
        unitString="months";
        break;
    case "w":
        unitString="weeks";
        break;
    case "h":
        unitString="hours";
        break;
    default:
        unitString="days";
        break;
    }

    return returnDate.add(unitString, num).toDate();
}

module.exports = function(urls, hashtags, user) {
    if (urls.length == 0) {
        return;
    }

    var valid = false;
    // reverse notation
    var pattern = new RegExp("^[y|m|w|d|h|m|s]([0-9]+)(?=niagadaer$)");
    var dateString = "";
    for (var iter = 0; iter < hashtags.length; iter++) {
        var hashtag = hashtags[iter];
        if (hashtag == "readagain") {
            valid = true;
            dateString = "d3";
            break;
        }

        // reverse the string since lookbehind does not work in javascript, we'll be using lookahead.
        var tagString = hashtag.split("").reverse().join("");
        var match = tagString.match(pattern);
        if (match !== null) {
            valid = true;
            dateString = match[0];
            break;
        }
    }

    if (valid) {
        for (var iter = 0; iter < urls.length; iter++) {
            var url = urls[iter];

            /*
            var post = new Post({
                url: url,
                user: user,
                next_reminder: unitToMilliseconds(dateString[0], parseInt(dateString.slice(1, dateString.length).split("").reverse().join("")))
            });

            post.save(function(err){
                if(err) console.log(err);
            }); */
        }
    }
};<commit_msg>Uncommented Post save.<commit_after>'use strict';
// all the functions in here should be generic - no platform specific code in here!
var mongoose = require('mongoose'),
    Post = mongoose.model('Post'),
    moment = require('moment'),
    config = require('./config');

function unitToMilliseconds(unitString, num) {
    var returnDate = moment();
    switch (unitString) {
    case "y":
        unitString="years";
        break;
    case "m":
        unitString="months";
        break;
    case "w":
        unitString="weeks";
        break;
    case "h":
        unitString="hours";
        break;
    default:
        unitString="days";
        break;
    }

    return returnDate.add(unitString, num).toDate();
}

module.exports = function(urls, hashtags, user) {
    if (urls.length == 0) {
        return;
    }

    var valid = false;
    // reverse notation
    var pattern = new RegExp("^[y|m|w|d|h|m|s]([0-9]+)(?=niagadaer$)");
    var dateString = "";
    for (var iter = 0; iter < hashtags.length; iter++) {
        var hashtag = hashtags[iter];
        if (hashtag == "readagain") {
            valid = true;
            dateString = "d3";
            break;
        }

        // reverse the string since lookbehind does not work in javascript, we'll be using lookahead.
        var tagString = hashtag.split("").reverse().join("");
        var match = tagString.match(pattern);
        if (match !== null) {
            valid = true;
            dateString = match[0];
            break;
        }
    }

    if (valid) {
        for (var iter = 0; iter < urls.length; iter++) {
            var url = urls[iter];

            var post = new Post({
                url: url,
                user: user,
                next_reminder: unitToMilliseconds(dateString[0], parseInt(dateString.slice(1, dateString.length).split("").reverse().join("")))
            });

            post.save(function(err){
                if(err) console.log(err);
            });
        }
    }
};<|endoftext|>


<commit_before>var _ = require('lodash');
var Q = require('q');
var path = require('path');
var axios = require('axios');
var url = require('url');
var urlJoin = require('urljoin.js');

var types = require('../types');
var errors = require('../errors');
var base64 = require('../utils/base64');
var arrayBuffer = require('../utils/arraybuffer');

// Get author from commit
function getAuthor(commit) {
    return  {
        "name": commit.commit.author.name,
        "email": commit.commit.author.email,
        "avatar": commit.author? commit.author.avatar_url : undefined
    };
}

// Normalize a patch
function normPatch(file) {
    return {
        filename: file.filename,
        patch: file.patch
    };
}

// Normalize a commit
function normCommit(commit) {
    var r = {
        "sha": commit.sha,
        "author": getAuthor(commit),
        "message": commit.commit.message,
        "date": commit.commit.author.date
    };
    if (commit.files) {
        r.files = _.map(commit.files, normPatch);
    }
    return r;
}

function Driver(options) {
    this.options = _.defaults({}, options || {}, {
        repository: null,
        host: "https://api.github.com",
        rawhost: "https://raw.githubusercontent.com",
        username: null,
        token: null,
        includeTokenInRaw: false

    });
    if (!this.options.repository) throw "GitHub driver requires a 'repository' option";
}

// Map some file informations
Driver.prototype.mapFile = function(ref, infos) {
    var rawUrl = infos.download_url || urlJoin(this.options.rawhost, this.options.repository+'/'+ref+'/'+infos.path);
    var parts = url.parse(rawUrl, true);
    parts.query.token = parts.query.token || encodeURIComponent(base64.encode(this.options.username + ':' + this.options.token));

    if (this.options.includeTokenInRaw) {
        rawUrl = url.format(parts);
    }

    return {
        "name": infos.name,
        "path": infos.path,
        "content": _.isString(infos.content)? arrayBuffer.fromBase64(infos.content.replace(/(\r\n|\n|\r)/gm,"")) : undefined,
        "sha": infos.sha,
        "type": infos.type,
        "size": infos.size,
        "url": rawUrl
    };
}

// Execute an HTTP API request
Driver.prototype.api = function (httpMethod, method, args, options) {
    var that = this;
    var opts = {
        method: httpMethod,
        url: urlJoin(this.options.host, "/repos/"+this.options.repository+"/"+method)+"?t="+Date.now(),
        headers: {
            'Accept': 'application/vnd.github.v3+json',
            'Content-type': 'application/json;charset=UTF-8'
        }
    };

    if (this.options.username) {
        opts.headers['Authorization'] = 'Basic ' + base64.encode(this.options.username + ':' + this.options.token);
    }

    if (httpMethod == 'get') opts.params = args;
    else opts.data = args;

    return Q(axios(opts))
    .get('data')
    .fail(function(response) {
        if (response instanceof Error) throw response;

        var e = new Error(response.data.message || "Error "+response.status+": "+response.data);
        e.statusCode = response.status;

        throw e;
    });
};

// Get informations about a file
Driver.prototype.stat = function(p, opts) {
    return this.api('get', 'contents'+path.join('/', p), {
        ref: opts.ref
    })
    .then(_.bind(this.mapFile, this, opts.ref));
};

// List files in a directory
Driver.prototype.readdir = function(p, opts) {
    var that = this;

    return this.api('get', 'contents'+path.join('/', p), {
        ref: opts.ref
    })
    .then(function(files) {
        return _.chain(files)
            .map(function(file) {
                return [file.name, that.mapFile(opts.ref, file)];
            })
            .object()
            .value();
    });
};

// Write a file
Driver.prototype.write = function(p, content, opts) {
    var encodedContent, that = this;

    encodedContent = arrayBuffer.enforceBase64(content);

    return that.stat(p, { ref: opts.ref })
    .then(function(infos) {
        return that.api("put", "contents/"+p, {
            branch: opts.ref,
            message: opts.message,
            content: encodedContent,
            sha: infos.sha,
            committer: that.options.committer
        });
    })
    .then(function(result) {
        result.content.content = encodedContent;
        return that.mapFile(opts.ref, result.content);
    });
};

// Create a new file
Driver.prototype.create = function(p, content, opts) {
    var encodedContent, that = this;

    encodedContent = arrayBuffer.enforceBase64(content);

    return this.stat(p, { ref: opts.ref })
    .then(function() {
        throw errors.fileAlreadyExist(p);
    }, function() {
        return that.api("put", "contents/"+p, {
            message: opts.message,
            branch: opts.ref,
            content: encodedContent,
            committer: that.options.committer
        });
    })
    .then(function(result) {
        result.content.content = encodedContent;
        return that.mapFile(opts.ref, result.content);
    });
};

// Delete a file
Driver.prototype.unlink = function(p, opts) {
    var that = this;

    return that.stat(p, { ref: opts.ref })
    .then(function(infos) {
        return that.api('delete', 'contents'+path.join('/', p), {
            message: opts.message,
            sha: infos.sha,
            branch: opts.ref,
            committer: that.options.committer
        });
    });
};

// List branches
Driver.prototype.listBranches = function(p, opts) {
    var that = this;

    return this.api('get', 'branches')
    .then(function(branches) {
        return _.map(branches, function(branch) {
            return {
                name: branch.name,
                commit: branch.commit.sha,
                is_local: branch.is_local
            };
        });
    });
};

// Create a branch
Driver.prototype.createBranch = function(name, from) {
    var that = this;

    return this.api("get", "branches/"+from)
    .then(function(branch) {
        return that.api("post", "git/refs", {
            "ref": "refs/heads/"+name,
            "sha": branch.commit.sha
        });
    });
};

// Remove a branch
Driver.prototype.removeBranch = function(name) {
    return this.api("delete", "git/refs/heads/"+name);
};

// Merge branches
Driver.prototype.mergeBranches = function(from, to, opts) {
    var that = this;

    return this.api("post", "merges", {
        base: to,
        head: from,
        commit_message: opts.message
    });
};

// List commits
// https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository
// todo: handle pagination and opts.start/opts.limit
Driver.prototype.listCommits = function(opts) {
    var that = this;

    return this.api("get", "commits", { sha: opts.ref })
    .then(function(commits) {
        return _.map(commits, normCommit);
    });
};

// Get a single commit
// https://developer.github.com/v3/repos/commits/#get-a-single-commit
Driver.prototype.getCommit = function(sha) {
    var that = this;

    return this.api("get", "commits/"+sha)
    .then(normCommit);
};

// Compare two commits
// https://developer.github.com/v3/repos/commits/#compare-two-commits
Driver.prototype.compareCommits = function(base, head, opts) {
    return this.api("get", "compare/"+[base, head].join('...'))
    .then(function(r) {
        return {
            "status": r.status,
            "ahead_by": r.ahead_by,
            "behind_by": r.behind_by,
            "total_commits": r.total_commits,
            "base": normCommit(r.base_commit),
            "head": normCommit(r.merge_base_commit),
            "commits": _.map(r.commits, normCommit),
            "files": _.map(r.files, normPatch)
        };
    });
};

// List remotes
// Not supported on api.github.com
Driver.prototype.listRemotes = function(opts) {
    return this.api("get", "remotes", opts);
};

// Edit a remote
// Not supported on api.github.com
Driver.prototype.editRemote = function(opts) {
    return this.api("post", "remotes", opts);
};

// Checkout a branch
// Not supported on api.github.com
Driver.prototype.checkout = function(opts) {
    return this.api("post", "checkout", opts);
};

// Fetch a remote
// Not supported on api.github.com
Driver.prototype.fetch = function(opts) {
    return this.api("post", "fetch", opts);
};

// Push to a remote
// Not supported on api.github.com
Driver.prototype.push = function(opts) {
    return this.api("post", "push", opts);
};

// Pull from a remote
// Not supported on api.github.com
Driver.prototype.pull = function(opts) {
    return this.api("post", "pull", opts);
};

Driver.id = "github";
module.exports = Driver;

<commit_msg>Limit file to be decoded by size<commit_after>var _ = require('lodash');
var Q = require('q');
var path = require('path');
var axios = require('axios');
var url = require('url');
var urlJoin = require('urljoin.js');

var types = require('../types');
var errors = require('../errors');
var base64 = require('../utils/base64');
var arrayBuffer = require('../utils/arraybuffer');

// 1MB max size to return
var CONTENT_MAX_SIZE = 1*1024*1024;

// Get author from commit
function getAuthor(commit) {
    return  {
        "name": commit.commit.author.name,
        "email": commit.commit.author.email,
        "avatar": commit.author? commit.author.avatar_url : undefined
    };
}

// Normalize a patch
function normPatch(file) {
    return {
        filename: file.filename,
        patch: file.patch
    };
}

// Normalize a commit
function normCommit(commit) {
    var r = {
        "sha": commit.sha,
        "author": getAuthor(commit),
        "message": commit.commit.message,
        "date": commit.commit.author.date
    };
    if (commit.files) {
        r.files = _.map(commit.files, normPatch);
    }
    return r;
}

function Driver(options) {
    this.options = _.defaults({}, options || {}, {
        repository: null,
        host: "https://api.github.com",
        rawhost: "https://raw.githubusercontent.com",
        username: null,
        token: null,
        includeTokenInRaw: false

    });
    if (!this.options.repository) throw "GitHub driver requires a 'repository' option";
}

// Map some file informations
Driver.prototype.mapFile = function(ref, infos) {
    var rawUrl = infos.download_url || urlJoin(this.options.rawhost, this.options.repository+'/'+ref+'/'+infos.path);
    var parts = url.parse(rawUrl, true);
    parts.query.token = parts.query.token || encodeURIComponent(base64.encode(this.options.username + ':' + this.options.token));

    if (this.options.includeTokenInRaw) {
        rawUrl = url.format(parts);
    }

    try {
        infos.content = (_.isString(infos.content) && infos.size < CONTENT_MAX_SIZE)? arrayBuffer.fromBase64(infos.content.replace(/(\r\n|\n|\r)/gm,"")) : undefined;
    } catch (e) {
        infos.content = undefined;
    }

    return {
        "name": infos.name,
        "path": infos.path,
        "content": infos.content,
        "sha": infos.sha,
        "type": infos.type,
        "size": infos.size,
        "url": rawUrl
    };
}

// Execute an HTTP API request
Driver.prototype.api = function (httpMethod, method, args, options) {
    var that = this;
    var opts = {
        method: httpMethod,
        url: urlJoin(this.options.host, "/repos/"+this.options.repository+"/"+method)+"?t="+Date.now(),
        headers: {
            'Accept': 'application/vnd.github.v3+json',
            'Content-type': 'application/json;charset=UTF-8'
        }
    };

    if (this.options.username) {
        opts.headers['Authorization'] = 'Basic ' + base64.encode(this.options.username + ':' + this.options.token);
    }

    if (httpMethod == 'get') opts.params = args;
    else opts.data = args;

    return Q(axios(opts))
    .get('data')
    .fail(function(response) {
        if (response instanceof Error) throw response;

        var e = new Error(response.data.message || "Error "+response.status+": "+response.data);
        e.statusCode = response.status;

        throw e;
    });
};

// Get informations about a file
Driver.prototype.stat = function(p, opts) {
    return this.api('get', 'contents'+path.join('/', p), {
        ref: opts.ref
    })
    .then(_.bind(this.mapFile, this, opts.ref));
};

// List files in a directory
Driver.prototype.readdir = function(p, opts) {
    var that = this;

    return this.api('get', 'contents'+path.join('/', p), {
        ref: opts.ref
    })
    .then(function(files) {
        return _.chain(files)
            .map(function(file) {
                return [file.name, that.mapFile(opts.ref, file)];
            })
            .object()
            .value();
    });
};

// Write a file
Driver.prototype.write = function(p, content, opts) {
    var encodedContent, that = this;

    encodedContent = arrayBuffer.enforceBase64(content);

    return that.stat(p, { ref: opts.ref })
    .then(function(infos) {
        return that.api("put", "contents/"+p, {
            branch: opts.ref,
            message: opts.message,
            content: encodedContent,
            sha: infos.sha,
            committer: that.options.committer
        });
    })
    .then(function(result) {
        result.content.content = encodedContent;
        return that.mapFile(opts.ref, result.content);
    });
};

// Create a new file
Driver.prototype.create = function(p, content, opts) {
    var encodedContent, that = this;

    encodedContent = arrayBuffer.enforceBase64(content);

    return this.stat(p, { ref: opts.ref })
    .then(function() {
        throw errors.fileAlreadyExist(p);
    }, function() {
        return that.api("put", "contents/"+p, {
            message: opts.message,
            branch: opts.ref,
            content: encodedContent,
            committer: that.options.committer
        });
    })
    .then(function(result) {
        result.content.content = encodedContent;
        return that.mapFile(opts.ref, result.content);
    });
};

// Delete a file
Driver.prototype.unlink = function(p, opts) {
    var that = this;

    return that.stat(p, { ref: opts.ref })
    .then(function(infos) {
        return that.api('delete', 'contents'+path.join('/', p), {
            message: opts.message,
            sha: infos.sha,
            branch: opts.ref,
            committer: that.options.committer
        });
    });
};

// List branches
Driver.prototype.listBranches = function(p, opts) {
    var that = this;

    return this.api('get', 'branches')
    .then(function(branches) {
        return _.map(branches, function(branch) {
            return {
                name: branch.name,
                commit: branch.commit.sha,
                is_local: branch.is_local
            };
        });
    });
};

// Create a branch
Driver.prototype.createBranch = function(name, from) {
    var that = this;

    return this.api("get", "branches/"+from)
    .then(function(branch) {
        return that.api("post", "git/refs", {
            "ref": "refs/heads/"+name,
            "sha": branch.commit.sha
        });
    });
};

// Remove a branch
Driver.prototype.removeBranch = function(name) {
    return this.api("delete", "git/refs/heads/"+name);
};

// Merge branches
Driver.prototype.mergeBranches = function(from, to, opts) {
    var that = this;

    return this.api("post", "merges", {
        base: to,
        head: from,
        commit_message: opts.message
    });
};

// List commits
// https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository
// todo: handle pagination and opts.start/opts.limit
Driver.prototype.listCommits = function(opts) {
    var that = this;

    return this.api("get", "commits", { sha: opts.ref })
    .then(function(commits) {
        return _.map(commits, normCommit);
    });
};

// Get a single commit
// https://developer.github.com/v3/repos/commits/#get-a-single-commit
Driver.prototype.getCommit = function(sha) {
    var that = this;

    return this.api("get", "commits/"+sha)
    .then(normCommit);
};

// Compare two commits
// https://developer.github.com/v3/repos/commits/#compare-two-commits
Driver.prototype.compareCommits = function(base, head, opts) {
    return this.api("get", "compare/"+[base, head].join('...'))
    .then(function(r) {
        return {
            "status": r.status,
            "ahead_by": r.ahead_by,
            "behind_by": r.behind_by,
            "total_commits": r.total_commits,
            "base": normCommit(r.base_commit),
            "head": normCommit(r.merge_base_commit),
            "commits": _.map(r.commits, normCommit),
            "files": _.map(r.files, normPatch)
        };
    });
};

// List remotes
// Not supported on api.github.com
Driver.prototype.listRemotes = function(opts) {
    return this.api("get", "remotes", opts);
};

// Edit a remote
// Not supported on api.github.com
Driver.prototype.editRemote = function(opts) {
    return this.api("post", "remotes", opts);
};

// Checkout a branch
// Not supported on api.github.com
Driver.prototype.checkout = function(opts) {
    return this.api("post", "checkout", opts);
};

// Fetch a remote
// Not supported on api.github.com
Driver.prototype.fetch = function(opts) {
    return this.api("post", "fetch", opts);
};

// Push to a remote
// Not supported on api.github.com
Driver.prototype.push = function(opts) {
    return this.api("post", "push", opts);
};

// Pull from a remote
// Not supported on api.github.com
Driver.prototype.pull = function(opts) {
    return this.api("post", "pull", opts);
};

Driver.id = "github";
module.exports = Driver;

<|endoftext|>


<commit_before>var HttpStatus = require('http-status-codes');
var _ = require('lodash');
var utils = require('../utils');

module.exports = function(config)  {

  var backendDefaults = {
    quietFailure: false,
    replaceOuter: false,
    dontPassUrl: true,
    leaveContentOnFail: true,
    addResponseHeaders: {}
  };

  return function selectBackend(req, res, next) {
    if (config.backend) {
      req.backend = _.find(config.backend, function(server) {
          if (server.pattern) { return new RegExp(server.pattern).test(req.url); }
          if (server.fn) {
            if (typeof config.functions[server.fn] == 'function') {
              return config.functions[server.fn](req, req.templateVars);
            }
          }
      });
    }
    if (!req.backend) {
      if (!res.headersSent) {
        res.writeHead(HttpStatus.NOT_FOUND);
      }
      return next({
        level: 'warn',
        message: 'Backend not found'
      });
    } else {
      req.backend = _.clone(_.defaults(req.backend, backendDefaults));
      req.backend.target = utils.render(req.backend.target, req.templateVars);
      req.backend.cacheKey = req.backend.cacheKey ? utils.render(req.backend.cacheKey, req.templateVars) : null;
      return next();
    }
  }
}
<commit_msg>add backend configuration as parameter<commit_after>var HttpStatus = require('http-status-codes');
var _ = require('lodash');
var utils = require('../utils');

module.exports = function(config)  {

  var backendDefaults = {
    quietFailure: false,
    replaceOuter: false,
    dontPassUrl: true,
    leaveContentOnFail: true,
    addResponseHeaders: {}
  };

  return function selectBackend(req, res, next) {
    if (config.backend) {
      req.backend = _.find(config.backend, function(server) {
          if (server.pattern) { return new RegExp(server.pattern).test(req.url); }
          if (server.fn) {
            if (typeof config.functions[server.fn] == 'function') {
              return config.functions[server.fn](req, req.templateVars, server);
            }
          }
      });
    }
    if (!req.backend) {
      if (!res.headersSent) {
        res.writeHead(HttpStatus.NOT_FOUND);
      }
      return next({
        level: 'warn',
        message: 'Backend not found'
      });
    } else {
      req.backend = _.clone(_.defaults(req.backend, backendDefaults));
      req.backend.target = utils.render(req.backend.target, req.templateVars);
      req.backend.cacheKey = req.backend.cacheKey ? utils.render(req.backend.cacheKey, req.templateVars) : null;
      return next();
    }
  }
}
<|endoftext|>


<commit_before>import path from 'path';
import log from './logger';
import _ from 'lodash';
import { fs } from 'appium-support';
import B from 'bluebird';

let STATIC_DIR = path.resolve(__dirname, '..', '..', '..', 'static');
if (_.isNull(path.resolve(__dirname).match(/build[\/\\]lib[\/\\]express$/))) {
  // in some contexts we are not in the build directory,
  // so we don't want to go back the extra level
  STATIC_DIR = path.resolve(__dirname, '..', '..', 'static');
}

async function guineaPigTemplate (req, res, page) {
  let delay = req.params.delay ? parseInt(req.params.delay, 10) : 0;
  let params = {
    serverTime: parseInt(Date.now() / 1000, 10),
    userAgent: req.headers['user-agent'],
    comment: 'None'
  };
  if (req.method === 'POST') {
    params.comment = req.body.comments || params.comment;
  }
  log.debug(`Sending guinea pig response with params: ${JSON.stringify(params)}`);
  await B.delay(delay);
  res.set('Content-Type', 'text/html');
  res.cookie('guineacookie1', 'i am a cookie value', {path: '/'});
  res.cookie('guineacookie2', 'cookié2', {path: '/'});
  res.cookie('guineacookie3', 'cant access this', {
    domain: '.blargimarg.com',
    path: '/'
  });
  res.send((await getTemplate(page))(params));
}

/*
 * Dynamic page mapped to /test/guinea-pig
 */
async function guineaPig (req, res) {
  return await guineaPigTemplate(req, res, 'guinea-pig.html');
}

/*
 * Dynamic page mapped to /test/guinea-pig
 */
async function guineaPigScrollable (req, res) {
  return await guineaPigTemplate(req, res, 'guinea-pig-scrollable.html');
}

/*
 * Dynamic page mapped to /welcome
 */
async function welcome (req, res) {
  let params = {message: 'Let\'s browse!'};
  log.debug(`Sending welcome response with params: ${JSON.stringify(params)}`);
  res.send((await getTemplate('welcome.html'))(params));
}

async function getTemplate (templateName) {
  let content = await fs.readFile(path.resolve(STATIC_DIR, 'test', templateName));
  return _.template(content.toString());
}

export { guineaPig, guineaPigScrollable, welcome, STATIC_DIR };
<commit_msg>Allow guinea pig delay to be in query<commit_after>import path from 'path';
import log from './logger';
import _ from 'lodash';
import { fs } from 'appium-support';
import B from 'bluebird';

let STATIC_DIR = path.resolve(__dirname, '..', '..', '..', 'static');
if (_.isNull(path.resolve(__dirname).match(/build[\/\\]lib[\/\\]express$/))) {
  // in some contexts we are not in the build directory,
  // so we don't want to go back the extra level
  STATIC_DIR = path.resolve(__dirname, '..', '..', 'static');
}

async function guineaPigTemplate (req, res, page) {
  let delay = parseInt(req.params.delay || req.query.delay || 0);
  let params = {
    serverTime: parseInt(Date.now() / 1000, 10),
    userAgent: req.headers['user-agent'],
    comment: 'None'
  };
  if (req.method === 'POST') {
    params.comment = req.body.comments || params.comment;
  }
  log.debug(`Sending guinea pig response with params: ${JSON.stringify(params)}`);
  if (delay) {
    log.debug(`Waiting ${delay}ms before responding`);
    await B.delay(delay);
  }
  res.set('Content-Type', 'text/html');
  res.cookie('guineacookie1', 'i am a cookie value', {path: '/'});
  res.cookie('guineacookie2', 'cookié2', {path: '/'});
  res.cookie('guineacookie3', 'cant access this', {
    domain: '.blargimarg.com',
    path: '/'
  });
  res.send((await getTemplate(page))(params));
}

/*
 * Dynamic page mapped to /test/guinea-pig
 */
async function guineaPig (req, res) {
  return await guineaPigTemplate(req, res, 'guinea-pig.html');
}

/*
 * Dynamic page mapped to /test/guinea-pig
 */
async function guineaPigScrollable (req, res) {
  return await guineaPigTemplate(req, res, 'guinea-pig-scrollable.html');
}

/*
 * Dynamic page mapped to /welcome
 */
async function welcome (req, res) {
  let params = {message: 'Let\'s browse!'};
  log.debug(`Sending welcome response with params: ${JSON.stringify(params)}`);
  res.send((await getTemplate('welcome.html'))(params));
}

async function getTemplate (templateName) {
  let content = await fs.readFile(path.resolve(STATIC_DIR, 'test', templateName));
  return _.template(content.toString());
}

export { guineaPig, guineaPigScrollable, welcome, STATIC_DIR };
<|endoftext|>


<commit_before>'use strict';

const assert = require('chai').assert;
const gplay = require('../index');
const R = require('ramda');

describe('Categories method', () => {
  it('should fetch valid list of categories', () => {
    return gplay.categories().then(categories => {
      assert.isArray(categories);
      assert.isTrue(categories.length > 0);
    });
  });

  it('should have all categories from constant list of categories', () => {
    return gplay.categories().then(categories => {
      const categoriesConst = Object.keys(gplay.category);
      assert.deepEqual(
        R.difference(categories, categoriesConst),
        [],
        'Google Play has categories that are not in "category" constant'
      );
      assert.deepEqual(
        R.difference(categoriesConst, categories),
        [],
        'There is some categories in the constant that were removed from Play Store'
      );
    });
  });
});
<commit_msg>skip categories test<commit_after>'use strict';

const assert = require('chai').assert;
const gplay = require('../index');
const R = require('ramda');

// FIXME skipping as this is behaving erratically (and it's not a fundamental function)
describe.skip('Categories method', () => {
  it('should fetch valid list of categories', () => {
    return gplay.categories().then(categories => {
      assert.isArray(categories);
      assert.isTrue(categories.length > 0);
    });
  });

  it('should have all categories from constant list of categories', () => {
    return gplay.categories().then(categories => {
      const categoriesConst = Object.keys(gplay.category);
      assert.deepEqual(
        R.difference(categories, categoriesConst),
        [],
        'Google Play has categories that are not in "category" constant'
      );
      assert.deepEqual(
        R.difference(categoriesConst, categories),
        [],
        'There is some categories in the constant that were removed from Play Store'
      );
    });
  });
});
<|endoftext|>


<commit_before>const helper = require('think-helper');
const assert = require('assert');
const Cookies = require('cookies');
const url = require('url');

const PARAM = Symbol('context-param');
const POST = Symbol('context-post');
const FILE = Symbol('context-file');
const COOKIE_STORE = Symbol('cookie-store');
const path = require('path');
const fs = require('fs');
const onFinished = require('on-finished');
const destroy = require('destroy');

/**
 * extend context
 */
module.exports = {
  /**
   * get userAgent header
   */
  get userAgent() {
    return this.header['user-agent'];
  },
  /**
   * is get request
   */
  get isGet() {
    return this.method === 'GET';
  },
  /**
   * is post request
   */
  get isPost() {
    return this.method === 'POST';
  },
  /**
   * is command line invoke
   */
  get isCli() {
    return this.method === 'CLI';
  },
  /**
   * get referer header
   */
  referer(onlyHost) {
    return this.referrer(onlyHost);
  },
  /**
   * get referer header
   */
  referrer(onlyHost) {
    const referrer = this.header['referer'];
    if (!referrer || !onlyHost) return referrer;
    return url.parse(referrer).hostname;
  },
  /**
   * is method
   */
  isMethod(method) {
    return this.method === method.toUpperCase();
  },
  /**
   * is ajax request
   */
  isAjax(method) {
    if (method && !this.isMethod(method)) return false;
    return this.header['x-requested-with'] === 'XMLHttpRequest';
  },
  /**
   * is jsonp request
   */
  isJsonp(callbackField = this.config('jsonpCallbackField')) {
    return !!this.param(callbackField);
  },
  /**
   * send jsonp data
   */
  jsonp(data, callbackField = this.config('jsonpCallbackField')) {
    let field = this.param(callbackField);
    // remove unsafe chars
    field = (field || '').replace(/[^\w.]/g, '');
    if (field) {
      data = `${field}(${JSON.stringify(data)})`;
    }
    this.type = this.config('jsonpContentType');
    this.body = data;
    return false;
  },
  /**
   * send json data
   */
  json(data) {
    this.type = this.config('jsonContentType');
    this.body = data;
    return false;
  },
  /**
   * send success data
   */
  success(data = '', message = '') {
    const obj = {
      [this.config('errnoField')]: 0,
      [this.config('errmsgField')]: message,
      data
    };
    this.type = this.config('jsonContentType');
    this.body = obj;
    return false;
  },
  /**
   * send fail data
   */
  fail(errno, errmsg = '', data = '') {
    let obj;
    if (helper.isObject(errno)) {
      obj = errno;
    } else {
      if (/^[A-Z_]+$/.test(errno)) {
        const messages = think.app.validators.messages || {};
        const msg = messages[errno];
        if (think.isArray(msg)) {
          [errno, errmsg] = msg;
        }
      }
      if (!think.isNumber(errno)) {
        [data, errmsg, errno] = [errmsg, errno, this.config('defaultErrno')];
      }
      obj = {
        [this.config('errnoField')]: errno,
        [this.config('errmsgField')]: errmsg
      };
      if (data) {
        obj.data = data;
      }
    }
    this.type = this.config('jsonContentType');
    this.body = obj;
    return false;
  },
  /**
   * set expires header
   */
  expires(time) {
    time = helper.ms(time);
    const date = new Date(Date.now() + time);
    this.set('Cache-Control', `max-age=${time}`);
    this.set('Expires', date.toUTCString());
  },
  /**
   * get or set configs
   * @param {String} name
   * @param {Mixed} value
   * @param {String} m
   */
  config(name, value, m = this.module) {
    return think.config(name, value, m);
  },
  /**
   * get or set query data
   * `query` or `get` is already used in koa
   * @param {String} name
   * @param {Mixed} value
   */
  param(name, value) {
    if (!this[PARAM]) {
      this[PARAM] = Object.assign({}, this.request._query || this.request.query);
      this.app.emit('filterParam', this[PARAM]);
    }
    if (!name) return this[PARAM];
    if (helper.isObject(name)) {
      this[PARAM] = Object.assign(this[PARAM], name);
      return this;
    }
    if (value === undefined) {
      // this.param('a,b')
      if (helper.isString(name) && name.indexOf(',') > -1) {
        name = name.split(/\s*,\s*/);
      }
      if (helper.isArray(name)) {
        const value = {};
        name.forEach(item => {
          const val = this[PARAM][item];
          if (val !== undefined) {
            value[item] = val;
          }
        });
        return value;
      }
      return this[PARAM][name];
    }
    this[PARAM][name] = value;
    return this;
  },
  /**
   * get or set post data
   * @param {String} name
   * @param {Mixed} value
   */
  post(name, value) {
    if (!this[POST]) {
      const json = this.request.body && this.request.body.post;
      this[POST] = think.isArray(json) ? Array.from(json) : Object.assign({}, json);
      this.app.emit('filterParam', this[POST]);
    }
    if (!name) return this[POST];
    if (helper.isObject(name)) {
      this[POST] = Object.assign(this[POST], name);
      return this;
    }
    if (value === undefined) {
      // this.param('a,b')
      if (helper.isString(name) && name.indexOf(',') > -1) {
        name = name.split(',');
      }
      if (helper.isArray(name)) {
        const value = {};
        name.forEach(item => {
          const val = this[POST][item];
          if (val !== undefined) {
            value[item] = val;
          }
        });
        return value;
      }
      return this[POST][name];
    }
    this[POST][name] = value;
    return this;
  },
  /**
   * get or set file data
   * @param {String} name
   * @param {Mixed} value
   */
  file(name, value) {
    if (!this[FILE]) {
      this[FILE] = Object.assign({}, this.request.body && this.request.body.file);
    }
    if (!name) return this[FILE];
    if (helper.isObject(name)) {
      this[FILE] = Object.assign(this[FILE], name);
      return this;
    }
    if (value === undefined) {
      return this[FILE][name];
    }
    this[FILE][name] = value;
    return this;
  },
  /**
   * get or set cookie
   * @param {String} name
   * @param {String} value
   * @param {Object} options
   */
  cookie(name, value, options = {}) {
    assert(name && helper.isString(name), 'cookie.name must be a string');
    options = Object.assign({}, this.config('cookie'), options);
    const instance = new Cookies(this.req, this.res, {
      keys: options.keys,
      secure: this.request.secure
    });

    if (!this[COOKIE_STORE]) this[COOKIE_STORE] = {};

    // get cookie
    if (value === undefined) {
      if (this[COOKIE_STORE][name] !== undefined) return this[COOKIE_STORE][name];
      return instance.get(name, options);
    }
    // remove cookie
    if (value === null) {
      delete this[COOKIE_STORE][name];
      // If the value is omitted, an outbound header with an expired date is used to delete the cookie.
      // https://github.com/pillarjs/cookies#cookiesset-name--value---options--
      return instance.set(name, undefined, options);
    }
    assert(helper.isString(value), 'cookie value must be a string');
    // http://browsercookielimits.squawky.net/
    if (value.length >= 4094) {
      this.app.emit('cookieLimit', {name, value, ctx: this});
    }
    this[COOKIE_STORE][name] = value;
    // set cookie
    return instance.set(name, value, options);
  },
  /**
   * get service
   * @param {String} name
   * @param {String} m
   */
  service(...args) {
    return think.service(...args);
  },
  /**
   * download
   * @param {String} filepath
   * @param {String} filename
   */
  download(filepath, filename = path.basename(filepath)) {
    assert(filepath, 'filepath can not be empty');
    const contentType = this.response.get('Content-Type');
    if (!contentType) {
      this.type = path.extname(filename);
    }
    const contentDisposition = this.response.get('Content-Disposition');
    if (!contentDisposition) {
      this.attachment(filename);
    }
    const stream = fs.createReadStream(filepath);
    this.body = stream;
    onFinished(this.res, () => {
      destroy(stream);
    });
    return false;
  }
};
<commit_msg>this.ctx.post() support 'a, b'<commit_after>const helper = require('think-helper');
const assert = require('assert');
const Cookies = require('cookies');
const url = require('url');

const PARAM = Symbol('context-param');
const POST = Symbol('context-post');
const FILE = Symbol('context-file');
const COOKIE_STORE = Symbol('cookie-store');
const path = require('path');
const fs = require('fs');
const onFinished = require('on-finished');
const destroy = require('destroy');

/**
 * extend context
 */
module.exports = {
  /**
   * get userAgent header
   */
  get userAgent() {
    return this.header['user-agent'];
  },
  /**
   * is get request
   */
  get isGet() {
    return this.method === 'GET';
  },
  /**
   * is post request
   */
  get isPost() {
    return this.method === 'POST';
  },
  /**
   * is command line invoke
   */
  get isCli() {
    return this.method === 'CLI';
  },
  /**
   * get referer header
   */
  referer(onlyHost) {
    return this.referrer(onlyHost);
  },
  /**
   * get referer header
   */
  referrer(onlyHost) {
    const referrer = this.header['referer'];
    if (!referrer || !onlyHost) return referrer;
    return url.parse(referrer).hostname;
  },
  /**
   * is method
   */
  isMethod(method) {
    return this.method === method.toUpperCase();
  },
  /**
   * is ajax request
   */
  isAjax(method) {
    if (method && !this.isMethod(method)) return false;
    return this.header['x-requested-with'] === 'XMLHttpRequest';
  },
  /**
   * is jsonp request
   */
  isJsonp(callbackField = this.config('jsonpCallbackField')) {
    return !!this.param(callbackField);
  },
  /**
   * send jsonp data
   */
  jsonp(data, callbackField = this.config('jsonpCallbackField')) {
    let field = this.param(callbackField);
    // remove unsafe chars
    field = (field || '').replace(/[^\w.]/g, '');
    if (field) {
      data = `${field}(${JSON.stringify(data)})`;
    }
    this.type = this.config('jsonpContentType');
    this.body = data;
    return false;
  },
  /**
   * send json data
   */
  json(data) {
    this.type = this.config('jsonContentType');
    this.body = data;
    return false;
  },
  /**
   * send success data
   */
  success(data = '', message = '') {
    const obj = {
      [this.config('errnoField')]: 0,
      [this.config('errmsgField')]: message,
      data
    };
    this.type = this.config('jsonContentType');
    this.body = obj;
    return false;
  },
  /**
   * send fail data
   */
  fail(errno, errmsg = '', data = '') {
    let obj;
    if (helper.isObject(errno)) {
      obj = errno;
    } else {
      if (/^[A-Z_]+$/.test(errno)) {
        const messages = think.app.validators.messages || {};
        const msg = messages[errno];
        if (think.isArray(msg)) {
          [errno, errmsg] = msg;
        }
      }
      if (!think.isNumber(errno)) {
        [data, errmsg, errno] = [errmsg, errno, this.config('defaultErrno')];
      }
      obj = {
        [this.config('errnoField')]: errno,
        [this.config('errmsgField')]: errmsg
      };
      if (data) {
        obj.data = data;
      }
    }
    this.type = this.config('jsonContentType');
    this.body = obj;
    return false;
  },
  /**
   * set expires header
   */
  expires(time) {
    time = helper.ms(time);
    const date = new Date(Date.now() + time);
    this.set('Cache-Control', `max-age=${time}`);
    this.set('Expires', date.toUTCString());
  },
  /**
   * get or set configs
   * @param {String} name
   * @param {Mixed} value
   * @param {String} m
   */
  config(name, value, m = this.module) {
    return think.config(name, value, m);
  },
  /**
   * get or set query data
   * `query` or `get` is already used in koa
   * @param {String} name
   * @param {Mixed} value
   */
  param(name, value) {
    if (!this[PARAM]) {
      this[PARAM] = Object.assign({}, this.request._query || this.request.query);
      this.app.emit('filterParam', this[PARAM]);
    }
    if (!name) return this[PARAM];
    if (helper.isObject(name)) {
      this[PARAM] = Object.assign(this[PARAM], name);
      return this;
    }
    if (value === undefined) {
      // this.param('a,b')
      if (helper.isString(name) && name.indexOf(',') > -1) {
        name = name.split(/\s*,\s*/);
      }
      if (helper.isArray(name)) {
        const value = {};
        name.forEach(item => {
          const val = this[PARAM][item];
          if (val !== undefined) {
            value[item] = val;
          }
        });
        return value;
      }
      return this[PARAM][name];
    }
    this[PARAM][name] = value;
    return this;
  },
  /**
   * get or set post data
   * @param {String} name
   * @param {Mixed} value
   */
  post(name, value) {
    if (!this[POST]) {
      const json = this.request.body && this.request.body.post;
      this[POST] = think.isArray(json) ? Array.from(json) : Object.assign({}, json);
      this.app.emit('filterParam', this[POST]);
    }
    if (!name) return this[POST];
    if (helper.isObject(name)) {
      this[POST] = Object.assign(this[POST], name);
      return this;
    }
    if (value === undefined) {
      // this.param('a,b')
      if (helper.isString(name) && name.indexOf(',') > -1) {
        name = name.split(/\s*,\s*/);
      }
      if (helper.isArray(name)) {
        const value = {};
        name.forEach(item => {
          const val = this[POST][item];
          if (val !== undefined) {
            value[item] = val;
          }
        });
        return value;
      }
      return this[POST][name];
    }
    this[POST][name] = value;
    return this;
  },
  /**
   * get or set file data
   * @param {String} name
   * @param {Mixed} value
   */
  file(name, value) {
    if (!this[FILE]) {
      this[FILE] = Object.assign({}, this.request.body && this.request.body.file);
    }
    if (!name) return this[FILE];
    if (helper.isObject(name)) {
      this[FILE] = Object.assign(this[FILE], name);
      return this;
    }
    if (value === undefined) {
      return this[FILE][name];
    }
    this[FILE][name] = value;
    return this;
  },
  /**
   * get or set cookie
   * @param {String} name
   * @param {String} value
   * @param {Object} options
   */
  cookie(name, value, options = {}) {
    assert(name && helper.isString(name), 'cookie.name must be a string');
    options = Object.assign({}, this.config('cookie'), options);
    const instance = new Cookies(this.req, this.res, {
      keys: options.keys,
      secure: this.request.secure
    });

    if (!this[COOKIE_STORE]) this[COOKIE_STORE] = {};

    // get cookie
    if (value === undefined) {
      if (this[COOKIE_STORE][name] !== undefined) return this[COOKIE_STORE][name];
      return instance.get(name, options);
    }
    // remove cookie
    if (value === null) {
      delete this[COOKIE_STORE][name];
      // If the value is omitted, an outbound header with an expired date is used to delete the cookie.
      // https://github.com/pillarjs/cookies#cookiesset-name--value---options--
      return instance.set(name, undefined, options);
    }
    assert(helper.isString(value), 'cookie value must be a string');
    // http://browsercookielimits.squawky.net/
    if (value.length >= 4094) {
      this.app.emit('cookieLimit', {name, value, ctx: this});
    }
    this[COOKIE_STORE][name] = value;
    // set cookie
    return instance.set(name, value, options);
  },
  /**
   * get service
   * @param {String} name
   * @param {String} m
   */
  service(...args) {
    return think.service(...args);
  },
  /**
   * download
   * @param {String} filepath
   * @param {String} filename
   */
  download(filepath, filename = path.basename(filepath)) {
    assert(filepath, 'filepath can not be empty');
    const contentType = this.response.get('Content-Type');
    if (!contentType) {
      this.type = path.extname(filename);
    }
    const contentDisposition = this.response.get('Content-Disposition');
    if (!contentDisposition) {
      this.attachment(filename);
    }
    const stream = fs.createReadStream(filepath);
    this.body = stream;
    onFinished(this.res, () => {
      destroy(stream);
    });
    return false;
  }
};
<|endoftext|>